home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / freetype.zip / ttins.pas < prev    next >
Pascal/Delphi Source File  |  1996-09-07  |  95KB  |  3,046 lines

  1. (**************************************************************************)
  2. (*                                                                        *)
  3. (*  TTINS : The FreeType project's TrueType bytecode interpreter !        *)
  4. (*                                                                        *)
  5. (*  TrueType interpreter how-to :                                         *)
  6. (*                                                                        *)
  7. (*  1. Init the Font Storage Pool and load the Max Profile table.         *)
  8. (*                                                                        *)
  9. (*  2. Load the CVT and all other tables. Set the glyph scale             *)
  10. (*                                                                        *)
  11. (*  3. Call 'Init_Interpreter' with the appropriate parms taken from      *)
  12. (*     the max table.                                                     *)
  13. (*                                                                        *)
  14. (*  4. Allocate a new code range with 'Alloc_CodeRange', and load the     *)
  15. (*     TrueType instructions in it.                                       *)
  16. (*                                                                        *)
  17. (*  5. Set 'Instruction_Trap' to TRUE if you want to debug step by step   *)
  18. (*     the flow of execution.                                             *)
  19. (*                                                                        *)
  20. (*  6. Initialize instruction pointer using 'Goto_CodeRange'              *)
  21. (*     DO NOT SET 'IP' DIRECTLY.                                          *)
  22. (*                                                                        *)
  23. (*  7. Call the function 'Run' !!                                         *)
  24. (*                                                                        *)
  25. (*                                                                        *)
  26. (*  NOTE : The interpreter still lacks several features, but seems to be  *)
  27. (*         reasonably functionning. Still a lot of debugging to do though *)
  28. (*                                                                        *)
  29. (*                                                                        *)
  30. (**************************************************************************)
  31.  
  32. unit TTINS;
  33.  
  34. interface
  35.  
  36. uses TTTypes, TTError, TTVars, TTCalc;
  37.  
  38. const
  39.   MaxCodeRanges = 3;
  40.   (* There can only be 3 active code ranges at once :  *)
  41.   (*   - the Font Program                              *)
  42.   (*   - the CVT  Program                              *)
  43.   (*   - a glyph's instructions set                    *)
  44.  
  45. type
  46.   PCodeRange = ^TCodeRange;
  47.   TCodeRange = record
  48.                  Base : PStorage;
  49.                  Size : Int;
  50.                end;
  51.  
  52.   (* defines a code range                                            *)
  53.   (*                                                                 *)
  54.   (* code ranges can be resident to a glyph ( i.e. the Font Program) *)
  55.   (* while some others are volatile ( Glyph instructions )           *)
  56.   (* tracking the state and presence of code ranges allows function  *)
  57.   (* and instruction definitions within a code range to be forgotten *)
  58.   (* when the range is discarded                                     *)
  59.  
  60.   TCodeRangeTable = array[1..MaxCodeRanges] of TCodeRange;
  61.  
  62.   (* defines a function/instruction definition record *)
  63.   TDefRecord = record
  64.                  Range  : Int;     (* in which code range is it located ? *)
  65.                  Start  : Int;     (* where does it start ?               *)
  66.                  Opc    : Byte;    (* function #, or instruction code     *)
  67.                  Active : boolean; (* is it active ?                      *)
  68.                end;
  69.  
  70.   PDefArray = ^TDefArray;
  71.   TDefArray = array[0..99] of TDefRecord;
  72.  
  73.   (* defines a call record, used to manage function calls *)
  74.   TCallRecord = record
  75.                   Caller_Range : Int;
  76.                   Caller_IP    : Int;
  77.                   Cur_Count    : Int;
  78.                   Cur_Restart  : Int;
  79.                 end;
  80.  
  81.   (* defines a simple call stack *)
  82.   TCallStack = array[0..99] of TCallRecord;
  83.   PCallStack = ^TCallStack;
  84.  
  85.   TDefTable = record
  86.                 N : Int;
  87.                 I : PDefArray;
  88.               end;
  89.  
  90.   DebugString = String;
  91.  
  92. var
  93.   CallTop   : int;         (* Call Stack top, 0 if empty *)
  94.   CallSize  : int;         (* Call Stack max size        *)
  95.   CallStack : PCallStack;  (* The current call stack     *)
  96.  
  97.   CodeRangeTable : TCodeRangeTable;
  98.   CodeRanges     : int;      (* number of currently used code ranges *)
  99.  
  100.   Code      : PByteArray;    (* Pointer to the current code segment *)
  101.   CodeSize  : int;           (* Size of the current code segment    *)
  102.   IP        : int;           (* Index of current instruction cursor *)
  103.  
  104.   Storage   : PStorage;      (* Pointer to the current storage area *)
  105.   StoreSize : int;           (* Size of the current storage area    *)
  106.  
  107.   Stack     : PStorage;      (* Pointer to the current interpreter stack *)
  108.   StackSize : int;           (* Size of the current interpreter stack    *)
  109.   top       : int;           (* Index of the interpreter stack top       *)
  110.  
  111.   period,
  112.   phase,                  (* Values used for the "Super Rounding" *)
  113.   threshold : F26dot6;
  114.  
  115.  
  116.   zp0,                    (* These are zone records                *)
  117.   zp1,                    (* Each record has pointers to original  *)
  118.   zp2,                    (* and current coordinates, as well as   *)
  119.   Twilight,               (* to the touch flags array.             *)
  120.   Pts       : TVecRecord; (* NOTE : Twilights and Pts are COPIED   *)
  121.                           (*        in zp0 to zp2 as needed        *)
  122.  
  123.   Contours  : TContourRecord; (* This record holds information about *)
  124.                               (* the current glyph's contours start  *)
  125.                               (* and end point indexes               *)
  126.  
  127.   Instruction_Trap : boolean; (* Instruction Debugging. Set to TRUE   *)
  128.                               (* to allow step-by-step trace          *)
  129.  
  130.   FDefs : TDefTable;
  131.   IDefs : TDefTable;
  132.  
  133.   Cur_Range : Int;
  134.  
  135. function  Init_Interpreter( var Max : TMaxProfile ) : boolean;
  136. (* Initialize Interpreter. The Font Storage Pool must be allocated, *)
  137. (* and the MaxProfile table must be loaded                          *)
  138.  
  139. function Alloc_CodeRange( ASize : Int; var ARange : int ) : Pointer;
  140. (* Allocate a new Code Range of size 'ASize'. Return a range index in ARange *)
  141. (* returns NIL on failure                                                    *)
  142.  
  143. function Discard_CodeRange( ARange : Int ): boolean;
  144. (* Discard a Code Range given its index *)
  145.  
  146. function Goto_CodeRange( ARange, AIP : Int ): boolean;
  147. (* Jump to a specified range, at address AIP *)
  148.  
  149. function Cur_Length : Int;
  150. (* Return length of current opcode, found at Code^[IP] *)
  151.  
  152. function Run : Boolean;
  153. (* Run the interpreter with the current code range and IP *)
  154.  
  155. procedure SetScale( PtSize, Resolution, EM : Int );
  156. (* Set the current glyph scale *)
  157.  
  158. function Get_CodeRange( ARange : Int ): PCodeRange;
  159. (* Should be used by the debuger only *)
  160.  
  161. implementation
  162.  
  163. (****************)
  164. (*  Cur_Length  *)
  165. (*              ************************************)
  166. (*                                                 *)
  167. (*  Return the length in bytes of current opcode   *)
  168. (*  at Code^[IP]                                   *)
  169. (*                                                 *)
  170. (***************************************************)
  171.  
  172. function Cur_Length : int;
  173. var
  174.   Op : byte;
  175. begin
  176.   Op := Code^[IP];
  177.   case Op of
  178.  
  179.     $40 : Cur_Length := Code^[IP+1] + 2;
  180.     $41 : Cur_Length := Code^[IP+1]*2 + 2;
  181.  
  182.     $B0..$B7 : Cur_Length := Op-$B0 + 2;
  183.     $B8..$BF : Cur_Length := (Op-$B8)*2 + 3;
  184.   else
  185.     Cur_Length := 1;
  186.   end;
  187. end;
  188.  
  189.  
  190. (*********************)
  191. (*  Alloc_CodeRange  *)
  192. (*                   **********************************************)
  193. (*                                                                *)
  194. (*  Allocate a new code range of size 'ASize' and returns a       *)
  195. (*  range index in 'ARange'. Returns NIL on failure               *)
  196. (*  ( out of code ranges, or out of memory )                      *)
  197. (*                                                                *)
  198. (*  NOTE : The Code Range is allocated by this function           *)
  199. (*                                                                *)
  200. (******************************************************************)
  201.  
  202. function Alloc_CodeRange( ASize : Int; var ARange : int ): Pointer;
  203. begin
  204.   if CodeRanges >= MaxCodeRanges then
  205.     begin
  206.       Error           := TT_ErrMsg_Out_Of_CodeRanges;
  207.       Alloc_CodeRange := nil;
  208.       exit;
  209.     end;
  210.  
  211.   inc( CodeRanges );
  212.   with CodeRangeTable[CodeRanges] do
  213.    begin
  214.  
  215.      if not Alloc( ASize, Pointer(Base) ) then
  216.        begin
  217.          Error           := TT_ErrMsg_Storage_Overflow;
  218.          Alloc_CodeRange := nil;
  219.          dec( CodeRanges );
  220.          exit;
  221.        end
  222.      else
  223.        Alloc_CodeRange := Base;
  224.  
  225.      ARange := CodeRanges;
  226.      Size   := ASize;
  227.  
  228.    end;
  229.  
  230. end;
  231.  
  232. (************************)
  233. (*  Discard_CodeRanges  *)
  234. (*                      **************************************)
  235. (*                                                           *)
  236. (*  Discards a coderange. The coderange must be the latest   *)
  237. (*  allocated. Returns FALSE on failure.                     *)
  238. (*                                                           *)
  239. (*  NOTE : This function DOES NOT reclaim storage used by    *)
  240. (*         the code range !!                                 *)
  241. (*                                                           *)
  242. (*************************************************************)
  243.  
  244. function Discard_CodeRange( ARange : Int ): boolean;
  245. var
  246.   i : int;
  247. begin
  248.  
  249.   if (ARange <> CodeRanges) or (ARange = 0) then
  250.     begin
  251.       Error             := TT_ErrMsg_Bad_Argument;
  252.       Discard_CodeRange := False;
  253.       exit;
  254.     end;
  255.  
  256.   (* Now discard all function and instruction definitions that *)
  257.   (* are located in this code range. NOTE : We do not restore  *)
  258.   (* the previous defs !!                                      *)
  259.  
  260.   for i := 0 to FDefs.N-1 do
  261.     with FDefs.I^[i] do
  262.      if Active and ( Range = ARange ) then
  263.        Active := False;
  264.  
  265.   for i := 0 to IDefs.N-1 do
  266.     with IDefs.I^[i] do
  267.       if Active and ( Range = ARange ) then
  268.         Active := False;
  269.  
  270.   dec( CodeRanges );
  271.  
  272. end;
  273.  
  274. (********************)
  275. (*  Goto_CodeRange  *)
  276. (*                  *******************************************)
  277. (*                                                            *)
  278. (*  Switch to a new code range during execution.              *)
  279. (*                                                            *)
  280. (**************************************************************)
  281.  
  282. function Goto_CodeRange( ARange, AIP : Int ): boolean;
  283. begin
  284.   if (ARange<=0) or (ARange>CodeRanges) then
  285.     begin
  286.       Error          := TT_ErrMsg_Bad_Argument;
  287.       Goto_CodeRange := False;
  288.       exit;
  289.     end;
  290.  
  291.   with CodeRangeTable[ARange] do
  292.     begin
  293.       (* NOTE : Because the last instruction of a program may be a call *)
  294.       (*        we may accept GOTOs to the first byte *after* the code  *)
  295.       (*        range                                                   *)
  296.       (* *)
  297.       (* XXXX A Rédiger plus clairement *)
  298.  
  299.       if AIP > Size then
  300.         begin
  301.           Error          := TT_ErrMsg_Code_Overflow;
  302.           Goto_CodeRange := False;
  303.           exit;
  304.         end;
  305.  
  306.       Code     := PByteArray(Base);
  307.       CodeSize := Size;
  308.       IP       := AIP;
  309.     end;
  310.  
  311.   Cur_Range := ARange;
  312.  
  313.   Goto_CodeRange := True;
  314. end;
  315.  
  316. function Get_CodeRange;
  317. begin
  318.   if (ARange<=0) or (ARange>CodeRanges) then
  319.     Get_CodeRange := nil
  320.   else
  321.     Get_CodeRange := @CodeRangeTable[ARange];
  322. end;
  323.  
  324. (**************)
  325. (*  GetShort  *)
  326. (*            *************************************)
  327. (*                                                *)
  328. (* This function returns a short integer stored   *)
  329. (* in the code segment at address IP.             *)
  330. (*                                                *)
  331. (* It should be made inline for best performance  *)
  332. (* but we want an easy an readable program        *)
  333. (*                                                *)
  334. (**************************************************)
  335.  
  336. function GetShort : Short;
  337. var
  338.   L : Array[0..1] of Byte;
  339. begin
  340.   L[1]     := Code^[IP]; inc(IP);
  341.   L[0]     := Code^[IP]; inc(IP);
  342.   GetShort := Short(L);
  343. end;
  344.  
  345. (*************)
  346. (*  GetLong  *)
  347. (*           **************************************)
  348. (*                                                *)
  349. (* This function returns a long integer stored    *)
  350. (* in the code segment at address IP.             *)
  351. (*                                                *)
  352. (* It should be inline for best performance       *)
  353. (* but we want an easy and readable program       *)
  354. (*                                                *)
  355. (**************************************************)
  356.  
  357. function GetLong : Long;
  358. var L : Array[0..3] of Byte;
  359. begin
  360.   L[3]    := Code^[IP]; inc(IP);
  361.   L[2]    := Code^[IP]; inc(IP);
  362.   L[1]    := Code^[IP]; inc(IP);
  363.   L[0]    := Code^[IP]; inc(IP);
  364.   GetLong := Long(L);
  365. end;
  366.  
  367. (***********)
  368. (*  Touch  *)
  369. (*         ****************************************)
  370. (*                                                *)
  371. (* Marks a point as touched according to the      *)
  372. (* freedom vector FV.                             *)
  373. (*                                                *)
  374. (**************************************************)
  375.  
  376. procedure Touch( var B : Byte );
  377. begin
  378.  with GS.freeVector do
  379.   begin
  380.    if x <> 0 then B:=B or TTFlagTouchedX;
  381.    if y <> 0 then B:=B or TTFlagTouchedY;
  382.   end
  383. end;
  384.  
  385. (**************)
  386. (*  SetScale  *)
  387. (*            *************************************)
  388. (*                                                *)
  389. (* Determines values for the current scale        *)
  390. (* quotient.                                      *)
  391. (*                                                *)
  392. (*   Pixels = ( FUnits * Scale1 ) / Scale2        *)
  393. (*                                                *)
  394. (*   Scale1 = PointSize * Resolution              *)
  395. (*   Scale2 = 72 * EM                             *)
  396. (*                                                *)
  397. (**************************************************)
  398.  
  399. procedure SetScale( PtSize, Resolution, EM : Int );
  400. begin
  401.   PointSize  := PtSize*64;
  402.   Scale1     := PtSize*Resolution;
  403.   Scale2     := 72*EM;
  404. end;
  405.  
  406. (************)
  407. (*  Scaled  *)
  408. (*          ***************************************)
  409. (*                                                *)
  410. (* Converts FUnits to Pixels, using the current   *)
  411. (* scale.                                         *)
  412. (*                                                *)
  413. (**************************************************)
  414.  
  415. function Scaled( L : Longint ) : LongInt;
  416. begin
  417.   Scaled := MulDiv( L, Scale1, Scale2 );
  418. end;
  419.  
  420. (****************)
  421. (*  Compensate  *)
  422. (*              ***********************************)
  423. (*                                                *)
  424. (* Compensate a distance according to its type    *)
  425. (* ( white, black or gray )                       *)
  426. (* # TO DO #                                      *)
  427. (*                                                *)
  428. (**************************************************)
  429.  
  430. function Compensate( var L : Long; Op : Byte ): boolean;
  431. var
  432.   R : Boolean;
  433. begin
  434.   R := Op < 3;
  435.   if not R then Error:=TT_ErrMsg_Invalid_Distance;
  436.   Compensate:= R;
  437. end;
  438.  
  439. (*******************)
  440. (*  SetSuperRound  *)
  441. (*                 ********************************)
  442. (*                                                *)
  443. (* Set Super Round parameters.                    *)
  444. (*                                                *)
  445. (**************************************************)
  446.  
  447. procedure SetSuperRound( GridPeriod : F26dot6; OpCode : Byte );
  448.  
  449. begin
  450.  
  451.   Case OpCode and $C0 of
  452.  
  453.    $00 : period := GridPeriod div 2;
  454.    $40 : period := GridPeriod;
  455.    $80 : period := GridPeriod * 2;
  456.  
  457.    (* This opcode is reserved, but ... *)
  458.  
  459.    $C0 : period := GridPeriod;
  460.   end;
  461.  
  462.   Case OpCode and $30 of
  463.  
  464.    $00 : phase := 0;
  465.    $10 : phase := period div 4;
  466.    $20 : phase := period div 2;
  467.    $30 : phase := gridPeriod*3 div 4;
  468.   end;
  469.  
  470.   if Opcode and $F = 0 then Threshold := Period-1
  471.    else
  472.     Threshold := (Integer( OpCode and $F )-4)*period div 8;
  473.  
  474.   period    := period div 256;
  475.   phase     := phase  div 256;
  476.   threshold := threshold div 256;
  477.  
  478. end;
  479.  
  480.  
  481. (*************)
  482. (*  ToRound  *)
  483. (*           **************************************)
  484. (*                                                *)
  485. (*  Rounds a parameter value according to the     *)
  486. (*  current round state.                          *)
  487. (*                                                *)
  488. (**************************************************)
  489.  
  490. function ToRound( L: Long ): Long;
  491.  
  492. var
  493.   L2 : LongInt;
  494.  
  495. begin
  496.   Case GS.roundState of
  497.  
  498.     TTRoundOff              : ToRound := L;
  499.  
  500.     TTRoundToHalfGrid       : ToRound := ( L and -64 ) + 32;
  501.  
  502.     TTRoundToGrid           : ToRound := ( L+32 ) and -64;
  503.  
  504.     TTRoundToDoubleGrid     : ToRound := (( 2*L+32 ) and -64) div 2;
  505.  
  506.     TTRoundUpToGrid         : ToRound := ( L+63 ) and -64;
  507.  
  508.     TTRoundDownToGrid       : ToRound := L and -64;
  509.  
  510.     TTRoundSuper : begin
  511.                      L2 := L;
  512.  
  513.                      (* TODO TODO                              *)
  514.                      (* We need to include engine compensation *)
  515.                      (* right here ! HOW ????!?                *)
  516.                      (*                                        *)
  517.  
  518.                       L := L-Phase;
  519.                       L := L+Threshold;
  520.                       L := Period*( L div Period );
  521.                       L := L+Phase;
  522.                       if (L<0) and (L2>0) then L:=Phase
  523.                       else
  524.                        if (L>0) and (L2<0) then L:=Phase-Period;
  525.  
  526.                       ToRound:=L;
  527.                     end
  528.    else
  529.     ToRound:=L;
  530.    end;
  531.  
  532. end;
  533.  
  534. (****************)
  535. (*  RoundPoint  *)
  536. (*              ***********************************)
  537. (*                                                *)
  538. (*  Rounds a point's coordinates according to     *)
  539. (*  the current round state and the projection    *)
  540. (*  vector.                                       *)
  541. (*                                                *)
  542. (**************************************************)
  543.  
  544. procedure RoundPoint( Var V : TVector );
  545. begin
  546.   if GS.projVector.y = 0 then
  547.     V.x:=ToRound(V.x)
  548.   else
  549.    if GS.projVector.x = 0 then
  550.     V.y:=ToRound(V.y)
  551.    else
  552.     begin
  553.      (* Right now, there is no rounding when projecting along *)
  554.      (* an axis that is not coordinate                        *)
  555.     end
  556. end;
  557.  
  558. (**************)
  559. (*  SkipCode  *)
  560. (*            *************************************************)
  561. (*                                                            *)
  562. (*  Increments the current instruction pointer to the next    *)
  563. (*  instruction, and verifies that we are still within the    *)
  564. (*  current code segment.                                     *)
  565. (*                                                            *)
  566. (*  Returns False when leaving code segment                   *)
  567. (*                                                            *)
  568. (**************************************************************)
  569.  
  570. function SkipCode : boolean;
  571. var L : Byte;
  572. begin
  573.   SkipCode := False;
  574.  
  575.   if IP < CodeSize then
  576.    begin
  577.     inc( IP, Cur_Length );
  578.     SkipCode := ( IP < CodeSize );
  579.    end;
  580. end;
  581.  
  582.  
  583. (**********)
  584. (*  Push  *)
  585. (*        ************************************************************)
  586. (*                                                                   *)
  587. (*  Pushes a long integer value on the parameter stack.              *)
  588. (*  Returns false in case of Stack_Overflow ( in which case the      *)
  589. (*  'Error' variable is set to TT_ErrMsg_Stack_Overflow              *)
  590. (*                                                                   *)
  591. (*********************************************************************)
  592.  
  593. function Push( l : Longint ) : boolean;
  594. begin
  595.   if top<stackSize then
  596.    begin
  597.     stack^[top]:=l;
  598.     inc( top );
  599.     Push:=True;
  600.    end
  601.   else
  602.    begin
  603.     Error:=TT_ErrMsg_Stack_Overflow;
  604.     Push:=False;
  605.    end;
  606. end;
  607.  
  608. (***********)
  609. (*  Push2  *)
  610. (*         *********************************************************)
  611. (*                                                                 *)
  612. (*  pushes TWO long integer values onto the parameter stack, and   *)
  613. (*  returns False in case of overflow.                             *)
  614. (*                                                                 *)
  615. (*  Note : L1 is pushed before L2                                  *)
  616. (*                                                                 *)
  617. (*******************************************************************)
  618.  
  619. function Push2( l1, l2 : LongInt ): boolean;
  620. begin
  621.   if top+2<=stackSize then
  622.    begin
  623.     stack^[top]:=l1;
  624.     stack^[top+1]:=l2;
  625.     inc( top, 2 );
  626.     Push2:=true;
  627.    end
  628.   else
  629.    begin
  630.     Error:=TT_ErrMsg_Stack_Overflow;
  631.     Push2:=False;
  632.    end
  633. end;
  634.  
  635. (*********)
  636. (*  Pop  *)
  637. (*       ***********************************************************)
  638. (*                                                                 *)
  639. (*  Pops a long integer from the stack. Returns False if the stack *)
  640. (*  is empty on call; in which case the 'Error' variable will be   *)
  641. (*  set to 'TT_ErrMsg_Too_Few_Arguments'.                          *)
  642. (*                                                                 *)
  643. (*******************************************************************)
  644.  
  645. function Pop( var L : LongInt ): boolean;
  646. begin
  647.   if top<1 then
  648.    begin
  649.     Error:=TT_ErrMsg_Too_Few_Arguments;
  650.     Pop:=False;
  651.    end
  652.   else
  653.    begin
  654.     dec( top );
  655.     L:=stack^[top];
  656.     Pop:=True;
  657.    end;
  658. end;
  659.  
  660. (**********)
  661. (*  Pop2  *)
  662. (*        **********************************************************)
  663. (*                                                                 *)
  664. (*  Pops TWO long ints  from the stack. Returns False is           *)
  665. (*  the stack is empty on call, r only holds one element.          *)
  666. (*                                                                 *)
  667. (*  Note : K is popped before L                                    *)
  668. (*                                                                 *)
  669. (*******************************************************************)
  670.  
  671. function Pop2( var K, L : LongInt ): boolean;
  672. begin
  673.   if top<2 then
  674.    begin
  675.     Error:=TT_ErrMsg_Too_Few_Arguments;
  676.     Pop2:=False;
  677.    end
  678.   else
  679.    begin
  680.     dec(top,2);
  681.     K:=stack^[top+1];
  682.     L:=stack^[top];
  683.     Pop2:=true;
  684.    end
  685. end;
  686.  
  687. (**************)
  688. (*  PopPoint  *)
  689. (*            *******************************************************)
  690. (*                                                                  *)
  691. (*  Pops a point reference L from the parameter stack. Checks that  *)
  692. (*  the reference is less than N. Returns False on failure, 'Error' *)
  693. (*  containing the Error raised ( empty stack or invalid ref )      *)
  694. (*                                                                  *)
  695. (********************************************************************)
  696.  
  697. function PopPoint( var L : LongInt; N : Int ) : boolean;
  698. begin
  699.   PopPoint:=False;
  700.   if Pop(L) then
  701.    if ( L<N ) then PopPoint:=True
  702.    else
  703.     Error:=TT_ErrMsg_Invalid_Reference;
  704. end;
  705.  
  706. (***************)
  707. (*  PopPoint2  *)
  708. (*             ******************************************************)
  709. (*                                                                  *)
  710. (*  Pops TWO point references, that must be less than N1 and N2,    *)
  711. (*  respectively. NOTE : K is popped before L                       *)
  712. (*                                                                  *)
  713. (********************************************************************)
  714.  
  715. function PopPoint2( var K, L : LongInt; N1, N2 : Int ): boolean;
  716. begin
  717.   PopPoint2:=False;
  718.   if Pop2( K,L ) then
  719.    if ( K<N1 ) and ( L<N2 ) then PopPoint2 := True
  720.     else
  721.      Error:=TT_ErrMsg_Invalid_Reference;
  722. end;
  723.  
  724.  
  725.  
  726. (****************************************************************)
  727. (*                                                              *)
  728. (*                    RUN                                       *)
  729. (*                                                              *)
  730. (*  This function executes a run of opcodes. It will exit       *)
  731. (*  in the following cases :                                    *)
  732. (*                                                              *)
  733. (*   - Errors ( in which case it returns FALSE )                *)
  734. (*                                                              *)
  735. (*   - Reaching the end of the main code range  (returns TRUE)  *)
  736. (*      reaching the end of a code range within a function      *)
  737. (*      call is an error.                                       *)
  738. (*                                                              *)
  739. (*   - After executing one single opcode, if the flag           *)
  740. (*     'Instruction_Trap' is set to TRUE. (returns TRUE)        *)
  741. (*                                                              *)
  742. (*  On exit whith TRUE, test IP < CodeSize to know wether it    *)
  743. (*  comes from a instruction trap or a normal termination       *)
  744. (*                                                              *)
  745. (*                                                              *)
  746. (*     Note : The documented DEBUG opcode pops a value from     *)
  747. (*            the stack. This behaviour is unsupported, here    *)
  748. (*            a DEBUG opcode is always an error.                *)
  749. (*                                                              *)
  750. (*                                                              *)
  751. (* THIS IS THE INTERPRETER'S MAIN LOOP                          *)
  752. (*                                                              *)
  753. (*  Instructions appear in the specs' order                     *)
  754. (*                                                              *)
  755. (****************************************************************)
  756.  
  757.  
  758. function Run : Boolean;
  759. label
  760.   SuiteLabel,
  761.   No_Error,
  762.   ErrorLabel;
  763.  
  764. var
  765.   OpCode   : Byte;
  766.  
  767.   nIFs     : Byte;  (* Number of nested Ifs *)
  768.  
  769.   zp       : TVecRecord;
  770.  
  771.   Vec      : TVector;
  772.   UVec1,
  773.   UVec2    : TUnitVector;
  774.  
  775.   Sign,
  776.   Out      : boolean;
  777.  
  778.   S        : Short;
  779.  
  780.   I, J     : Int;
  781.  
  782.   T        : Int64;
  783.  
  784.   A, B, C,
  785.   K,
  786.   L        : Long;
  787. begin
  788.  
  789.   Repeat
  790.  
  791.    OpCode:=Code^[IP];
  792.    Case OpCode of
  793.  
  794. (****************************************************************)
  795. (*                                                              *)
  796. (* MANAGING THE STACK                                           *)
  797. (*                                                              *)
  798. (*  Instructions appear in the specs' order                     *)
  799. (*                                                              *)
  800. (****************************************************************)
  801.  
  802. (*******************************************)
  803. (* DUP[]     : Duplicate top stack element *)
  804. (* CodeRange : $20                         *)
  805.  
  806.    $20 : if top=0 then
  807.           begin
  808.            Error := TT_ErrMsg_Too_Few_Arguments;
  809.            goto ErrorLabel;
  810.           end
  811.          else
  812.           if not Push( Stack^[top-1] ) then goto ErrorLabel;
  813.  
  814. (*******************************************)
  815. (* POP[]     : POPs the stack's top elt.   *)
  816. (* CodeRange : $21                         *)
  817.  
  818.    $21 : if not Pop(L) then goto ErrorLabel;
  819.  
  820.  
  821. (*******************************************)
  822. (* CLEAR[]   : Clear the entire stack      *)
  823. (* CodeRange : $22                         *)
  824.  
  825.    $22 : top:=0;
  826.  
  827. (*******************************************)
  828. (* SWAP[]    : Swap the top two elements   *)
  829. (* CodeRange : $23                         *)
  830.  
  831.    $23 : if top<2 then
  832.           begin
  833.            Error:=TT_ErrMsg_Too_Few_Arguments;
  834.            goto ErrorLabel;
  835.           end
  836.          else
  837.           begin
  838.            L:=stack^[top-1];
  839.            stack^[top-1]:=stack^[top-2];
  840.            stack^[top-2]:=L;
  841.           end;
  842.  
  843. (*******************************************)
  844. (* DEPTH[]   : return the stack depth      *)
  845. (* CodeRange : $24                         *)
  846.  
  847.    $24 : if not Push(top) then goto ErrorLabel;
  848.  
  849. (*******************************************)
  850. (* CINDEX[]  : copy indexed element        *)
  851. (* CodeRange : $25                         *)
  852.  
  853.    $25 : begin
  854.           if not Pop(L) then goto ErrorLabel;
  855.           if (L=0) or (top<L) then
  856.            begin
  857.             Error:=TT_ErrMsg_Bad_Argument;
  858.             goto ErrorLabel;
  859.            end;
  860.           if not Push( stack^[top-l] ) then goto ErrorLabel;
  861.          end;
  862.  
  863. (*******************************************)
  864. (* MINDEX[]  : move indexed element        *)
  865. (* CodeRange : $26                         *)
  866.  
  867.    $26 : begin
  868.           if not Pop(L) then goto ErrorLabel;
  869.  
  870.           if (L=0) or (top<L) then
  871.            begin
  872.             Error:=TT_ErrMsg_Bad_Argument;
  873.             goto ErrorLabel;
  874.            end;
  875.  
  876.           K:= stack^[top-l];
  877.           move( stack^[top-l+1], stack^[top-l], l-1 );
  878.           stack^[top-1]:=k;
  879.          end;
  880.  
  881. (*******************************************)
  882. (* ROLL[]    : roll top three elements     *)
  883. (* CodeRange : $8A                         *)
  884.  
  885.    $8A : if top<3 then
  886.           begin
  887.            Error:=TT_ErrMsg_Too_Few_Arguments;
  888.            goto ErrorLabel;
  889.           end
  890.          else
  891.           begin
  892.            A:=stack^[top-3];
  893.            B:=stack^[top-2];
  894.            C:=stack^[top-1];
  895.  
  896.            stack^[top-1]:=A;
  897.            stack^[top-2]:=C;
  898.            stack^[top-3]:=B;
  899.           end;
  900.  
  901.  
  902. (****************************************************************)
  903. (*                                                              *)
  904. (* MANAGING THE FLOW OF CONTROL                                 *)
  905. (*                                                              *)
  906. (*  Instructions appear in the specs' order                     *)
  907. (*                                                              *)
  908. (****************************************************************)
  909.  
  910. (*******************************************)
  911. (* IF[]      : IF test                     *)
  912. (* CodeRange : $58                         *)
  913.  
  914.    $58 : begin
  915.           if not Pop(L) then goto ErrorLabel;
  916.           if L=0 then
  917.            begin
  918.             nIfs:=1;
  919.  
  920.             Out:=False;
  921.             Repeat
  922.  
  923.              if not SkipCode then goto ErrorLabel;
  924.  
  925.              Case Code^[IP] of
  926.  
  927.              (* IF *)
  928.               $58 : inc( nIfs );
  929.  
  930.              (* ELSE *)
  931.               $1B : out:= nIfs=1;
  932.  
  933.              (* EIF *)
  934.               $59 : begin
  935.                      dec( nIfs );
  936.                      out:= nIfs=0;
  937.                     end;
  938.              end;
  939.  
  940.             until Out;
  941.            end;
  942.          end;
  943.  
  944. (*******************************************)
  945. (* ELSE[]    : ELSE                        *)
  946. (* CodeRange : $1B                         *)
  947.  
  948.    $1B : begin
  949.           nIfs:=1;
  950.  
  951.            Repeat
  952.  
  953.             if not SkipCode then goto ErrorLabel;
  954.  
  955.             Case Code^[IP] of
  956.  
  957.             (* IF *)
  958.              $58 : inc( nIfs );
  959.  
  960.             (* EIF *)
  961.              $59 : dec( nIfs );
  962.             end;
  963.  
  964.            until nIfs=0;
  965.          end;
  966.  
  967. (*******************************************)
  968. (* EIF[]     : End IF                      *)
  969. (* CodeRange : $59                         *)
  970.  
  971.    $59 : ; (* Intentional *)
  972.  
  973. (*******************************************)
  974. (* JROT[]    : Jump Relative On True       *)
  975. (* CodeRange : $78                         *)
  976.  
  977.    $78 : begin
  978.           if not Pop2( K, L ) then goto ErrorLabel;
  979.  
  980.           if K<>0 then
  981.            begin
  982.             Inc( IP, L );
  983.             goto SuiteLabel;
  984.            end;
  985.          end;
  986.  
  987. (*******************************************)
  988. (* JMPR[]    : JuMP Relative               *)
  989. (* CodeRange : $1C                         *)
  990.  
  991.    $1C : begin
  992.           if not Pop( K ) then goto ErrorLabel;
  993.           Inc( IP, K );
  994.           goto SuiteLabel;
  995.          end;
  996.  
  997.  
  998. (*******************************************)
  999. (* JROF[]    : Jump Relative On False      *)
  1000. (* CodeRange : $79                         *)
  1001.  
  1002.    $79 : begin
  1003.           if not Pop2( K, L ) then goto ErrorLabel;
  1004.  
  1005.           if K=0 then
  1006.            begin
  1007.             Inc( IP, L );
  1008.             goto SuiteLabel;
  1009.            end;
  1010.          end;
  1011.  
  1012. (****************************************************************)
  1013. (*                                                              *)
  1014. (* LOGICAL FUNCTIONS                                            *)
  1015. (*                                                              *)
  1016. (*  Instructions appear in the specs' order                     *)
  1017. (*                                                              *)
  1018. (****************************************************************)
  1019.  
  1020. (*******************************************)
  1021. (* LT[]      : Less Than                   *)
  1022. (* CodeRange : $50                         *)
  1023.  
  1024.    $50 : begin
  1025.           if top<2 then
  1026.            begin
  1027.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1028.             goto ErrorLabel;
  1029.            end;
  1030.  
  1031.           (* This is an UNSIGNED LONG comparison *)
  1032.           if stack^[top-1] < stack^[top-2] then
  1033.            Stack^[top-2]:=1 else Stack^[top-2]:=0;
  1034.  
  1035.           dec(top);
  1036.          end;
  1037.  
  1038. (*******************************************)
  1039. (* LTEQ[]    : Less Than or EQual          *)
  1040. (* CodeRange : $51                         *)
  1041.  
  1042.    $51 : begin
  1043.           if top<2 then
  1044.            begin
  1045.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1046.             goto ErrorLabel;
  1047.            end;
  1048.  
  1049.           (* This is an UNSIGNED LONG comparison *)
  1050.           if stack^[top-1] <= stack^[top-2]
  1051.            then
  1052.             Stack^[top-2] := 1
  1053.            else
  1054.             Stack^[top-2] := 0;
  1055.  
  1056.           dec(top);
  1057.          end;
  1058.  
  1059. (*******************************************)
  1060. (* GT[]      : Greater Than                *)
  1061. (* CodeRange : $52                         *)
  1062.  
  1063.    $52 : begin
  1064.           if top<2 then
  1065.            begin
  1066.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1067.             goto ErrorLabel;
  1068.            end;
  1069.  
  1070.           (* This is an UNSIGNED LONG comparison *)
  1071.           if stack^[top-1] > stack^[top-2] then
  1072.            Stack^[top-2]:=1 else Stack^[top-2]:=0;
  1073.  
  1074.           dec(top);
  1075.          end;
  1076.  
  1077. (*******************************************)
  1078. (* GTEQ[]    : Greater Than or EQual       *)
  1079. (* CodeRange : $53                         *)
  1080.  
  1081.    $53 : begin
  1082.           if top<2 then
  1083.            begin
  1084.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1085.             goto ErrorLabel;
  1086.            end;
  1087.  
  1088.           (* This is an UNSIGNED LONG comparison *)
  1089.           if stack^[top-1] >= stack^[top-2] then
  1090.            Stack^[top-2]:=1 else Stack^[top-2]:=0;
  1091.  
  1092.           dec(top);
  1093.          end;
  1094.  
  1095. (*******************************************)
  1096. (* EQ[]      : EQual                       *)
  1097. (* CodeRange : $54                         *)
  1098.  
  1099.    $54 : begin
  1100.           if top<2 then
  1101.            begin
  1102.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1103.             goto ErrorLabel;
  1104.            end;
  1105.  
  1106.           (* This is an UNSIGNED LONG comparison *)
  1107.           if stack^[top-1] = stack^[top-2] then
  1108.            Stack^[top-2]:=1 else Stack^[top-2]:=0;
  1109.  
  1110.           dec(top);
  1111.          end;
  1112.  
  1113. (*******************************************)
  1114. (* NEQ[]     : Not EQual                   *)
  1115. (* CodeRange : $55                         *)
  1116.  
  1117.    $55 : begin
  1118.           if top<2 then
  1119.            begin
  1120.             Error:=TT_ErrMsg_Too_Few_Arguments;
  1121.             goto ErrorLabel;
  1122.            end;
  1123.  
  1124.           (* This is an UNSIGNED LONG comparison *)
  1125.           if stack^[top-1] <> stack^[top-2] then
  1126.            Stack^[top-2]:=1 else Stack^[top-2]:=0;
  1127.  
  1128.           dec(top);
  1129.          end;
  1130.  
  1131. (*******************************************)
  1132. (* ODD[]     : Odd                         *)
  1133. (* CodeRange : $56                         *)
  1134.  
  1135.    $56 : begin
  1136.           if not Pop(L) then goto ErrorLabel;
  1137.           L:=ToRound(L);
  1138.           if L and 127 = 64 then L:=1 else L:=0;
  1139.           if not Push(L) then goto ErrorLabel;
  1140.          end;
  1141.  
  1142. (*******************************************)
  1143. (* EVEN[]    : Even                        *)
  1144. (* CodeRange : $57                         *)
  1145.  
  1146.    $57 : begin
  1147.           if not Pop(L) then goto ErrorLabel;
  1148.           L:=ToRound(L);
  1149.           if L and 127 = 0 then L:=1 else L:=0;
  1150.           if not Push(L) then goto ErrorLabel;
  1151.          end;
  1152.  
  1153. (*******************************************)
  1154. (* AND[]     : logical AND                 *)
  1155. (* CodeRange : $5A                         *)
  1156.  
  1157.    $5A : begin
  1158.           if not Pop2( K, L ) then goto ErrorLabel;
  1159.           if (K<>0) and (L<>0) then L:=1 else L:=0;
  1160.           if not Push(L) then goto ErrorLabel;
  1161.          end;
  1162.  
  1163. (*******************************************)
  1164. (* OR[]      : logical OR                  *)
  1165. (* CodeRange : $5B                         *)
  1166.  
  1167.    $5B : begin
  1168.           if not Pop2( K, L ) then goto ErrorLabel;
  1169.           if (K<>0) or (L<>0) then L:=1 else L:=0;
  1170.           if not Push(L) then goto ErrorLabel;
  1171.          end;
  1172.  
  1173. (*******************************************)
  1174. (* NOT[]     : logical NOT                 *)
  1175. (* CodeRange : $5C                         *)
  1176.  
  1177.    $5C : begin
  1178.           if not Pop(L) then goto ErrorLabel;
  1179.           if L<>0 then L:=1 else L:=0;
  1180.           if not Push(L) then goto ErrorLabel;
  1181.          end;
  1182.  
  1183. (****************************************************************)
  1184. (*                                                              *)
  1185. (* ARITHMETIC AND MATH INSTRUCTIONS                             *)
  1186. (*                                                              *)
  1187. (*  Instructions appear in the specs' order                     *)
  1188. (*                                                              *)
  1189. (****************************************************************)
  1190.  
  1191. (*******************************************)
  1192. (* ADD[]     : ADD                         *)
  1193. (* CodeRange : $60                         *)
  1194.  
  1195.    $60 : begin
  1196.           if not Pop2( K, L ) then goto ErrorLabel;
  1197.           if not Push(L+K) then goto ErrorLabel;
  1198.          end;
  1199.  
  1200. (*******************************************)
  1201. (* SUB[]     : SUBstract                   *)
  1202. (* CodeRange : $61                         *)
  1203.  
  1204.    $61 : begin
  1205.           if not Pop2( K, L ) then goto ErrorLabel;
  1206.           if not Push(L-K) then goto ErrorLabel;
  1207.          end;
  1208.  
  1209. (*******************************************)
  1210. (* DIV[]     : DIVide                      *)
  1211. (* CodeRange : $62                         *)
  1212.  
  1213.    $62 : begin
  1214.           if not Pop2( K, L ) then goto ErrorLabel;
  1215.  
  1216.           if K=0 then
  1217.            begin
  1218.             Error:=TT_ErrMsg_Divide_By_Zero;
  1219.             goto ErrorLabel;
  1220.            end;
  1221.  
  1222.           if not Push( L div K ) then goto ErrorLabel;
  1223.          end;
  1224.  
  1225. (*******************************************)
  1226. (* MUL[]     : MULtiply                    *)
  1227. (* CodeRange : $63                         *)
  1228.  
  1229.    $63 : begin
  1230.           if not Pop2( K, L ) then goto ErrorLabel;
  1231.  
  1232.           if not Push( L * K ) then goto ErrorLabel;
  1233.          end;
  1234.  
  1235. (*******************************************)
  1236. (* ABS[]     : ABSolute value              *)
  1237. (* CodeRange : $64                         *)
  1238.  
  1239.    $64 : begin
  1240.           if not Pop(L) then goto ErrorLabel;
  1241.           if not Push(Abs(L)) then goto ErrorLabel;
  1242.          end;
  1243.  
  1244. (*******************************************)
  1245. (* NEG[]     : NEGate                      *)
  1246. (* CodeRange : $65                         *)
  1247.  
  1248.    $65 : begin
  1249.           if not Pop(L) then goto ErrorLabel;
  1250.           if not Push(-L) then goto ErrorLabel;
  1251.          end;
  1252.  
  1253. (*******************************************)
  1254. (* FLOOR[]   : FLOOR                       *)
  1255. (* CodeRange : $66                         *)
  1256.  
  1257.    $66 : begin
  1258.           if not Pop(L) then goto ErrorLabel;
  1259.           if not Push( L and -64 ) then goto ErrorLabel;
  1260.          end;
  1261.  
  1262. (*******************************************)
  1263. (* CEILING[] : CEILING                     *)
  1264. (* CodeRange : $67                         *)
  1265.  
  1266.    $67 : begin
  1267.           if not Pop(L) then goto ErrorLabel;
  1268.           if not Push( (L+63) and -64 ) then goto ErrorLabel;
  1269.          end;
  1270.  
  1271. (*******************************************)
  1272. (* MAX[]     : MAXimum                     *)
  1273. (* CodeRange : $68                         *)
  1274.  
  1275.    $8B : begin
  1276.           if not Pop2( K, L ) then goto ErrorLabel;
  1277.  
  1278.           if K>L then L:=K;
  1279.           if not Push( L ) then goto ErrorLabel;
  1280.          end;
  1281.  
  1282. (*******************************************)
  1283. (* MIN[]     : MINimum                     *)
  1284. (* CodeRange : $69                         *)
  1285.  
  1286.    $8C : begin
  1287.           if not Pop2( K, L ) then goto ErrorLabel;
  1288.  
  1289.           if K<L then L:=K;
  1290.           if not Push( L ) then goto ErrorLabel;
  1291.          end;
  1292.  
  1293. (****************************************************************)
  1294. (*                                                              *)
  1295. (* COMPENSATING FOR THE ENGINE CHARACTERISTICS                  *)
  1296. (*                                                              *)
  1297. (*  Instructions appear in the specs' order                     *)
  1298. (*                                                              *)
  1299. (****************************************************************)
  1300.  
  1301. (*******************************************)
  1302. (* ROUND[ab] : ROUND value                 *)
  1303. (* CodeRange : $68-$6B                     *)
  1304.  
  1305.    $68..$6A : begin
  1306.                if ( not Pop(L) ) then goto ErrorLabel;
  1307.                Compensate( L, Opcode-$68 );
  1308.                L:=ToRound(L);
  1309.                if not Push(L) then goto ErrorLabel;
  1310.               end;
  1311.  
  1312.    $6B : begin
  1313.           Error:=TT_ErrMsg_Invalid_Opcode;
  1314.           goto ErrorLabel;
  1315.          end;
  1316.  
  1317. (*******************************************)
  1318. (* NROUND[ab]: No ROUNDing of value        *)
  1319. (* CodeRange : $6C-$6F                     *)
  1320.  
  1321.    $6C..$6E : begin
  1322.                if ( not Pop(L) ) then goto ErrorLabel;
  1323.                Compensate( L, Opcode-$6C );
  1324.                if not Push(L) then goto ErrorLabel;
  1325.               end;
  1326.  
  1327.    $6F : begin
  1328.           Error := TT_ErrMsg_Invalid_Opcode;
  1329.           goto ErrorLabel;
  1330.          end;
  1331.  
  1332. (****************************************************************)
  1333. (*                                                              *)
  1334. (* DEFINING AND USING FUNCTIONS AND INSTRUCTIONS                *)
  1335. (*                                                              *)
  1336. (*  Instructions appear in the specs' order                     *)
  1337. (*                                                              *)
  1338. (****************************************************************)
  1339.  
  1340. (*******************************************)
  1341. (* FDEF[]    : Function DEFinition         *)
  1342. (* CodeRange : $2C                         *)
  1343.  
  1344.    $2C : begin
  1345.            if not Pop(L) then goto ErrorLabel;
  1346.  
  1347.            if word(L) >= FDefs.N then
  1348.              begin
  1349.                Error := TT_ErrMsg_Invalid_Reference;
  1350.                goto ErrorLabel;
  1351.              end;
  1352.  
  1353.            (* XXX *)
  1354.  
  1355.            (* We could maybe do something when the function *)
  1356.            (* is redefined ?                                *)
  1357.  
  1358.            with FDefs.I^[L] do
  1359.              begin
  1360.                Range  := Cur_Range;
  1361.                OpCode := Opcode;
  1362.                Start  := IP+1;
  1363.                Active := True;
  1364.              end;
  1365.  
  1366.            (* now skip the whole function definition *)
  1367.            (* we don't allow nested IDEFS & FDEFs    *)
  1368.  
  1369.            while SkipCode do
  1370.  
  1371.              case Code^[IP] of
  1372.  
  1373.                $89,  (* IDEF *)
  1374.                $2C : (* FDEF *)
  1375.                      begin
  1376.                        Error := TT_ErrMsg_Nested_Defs;
  1377.                        goto ErrorLabel;
  1378.                      end;
  1379.  
  1380.                $2D : (* ENDF *)
  1381.                      begin
  1382.                        SkipCode;
  1383.                        goto SuiteLabel;
  1384.                      end;
  1385.              end;
  1386.  
  1387.            goto ErrorLabel;
  1388.  
  1389.          end;
  1390.  
  1391. (*******************************************)
  1392. (* ENDF[]    : END Function definition     *)
  1393. (* CodeRange : $2D                         *)
  1394.  
  1395.    $2D : begin
  1396.           if CallTop <= 0 then   (* We encountered an ENDF without a call *)
  1397.             begin
  1398.               Error := TT_ErrMsg_ENDF_in_Exec_Stream;
  1399.               goto ErrorLabel;
  1400.             end
  1401.           else
  1402.             begin    (* End of function call *)
  1403.               dec( CallTop );
  1404.  
  1405.               with CallStack^[CallTop] do
  1406.                begin
  1407.                 dec( Cur_Count );
  1408.  
  1409.                 if Cur_Count > 0 then
  1410.  
  1411.                   begin
  1412.                     (* Loop the current function *)
  1413.                     IP := Cur_Restart;
  1414.                     inc( CallTop );
  1415.                   end
  1416.  
  1417.                 else
  1418.                   (* exit the current call frame *)
  1419.                   (* NOTE : When the last intruction of a program      *)
  1420.                   (*        is a CALL or LOOPCALL, the return address  *)
  1421.                   (*        is always out of the code range. This is   *)
  1422.                   (*        valid, though, which is why we do not test *)
  1423.                   (*        the result of Goto_CodeRange here !!       *)
  1424.  
  1425.                   Goto_CodeRange( Caller_Range, Caller_IP )
  1426.                end;
  1427.  
  1428.               goto SuiteLabel;
  1429.  
  1430.             end
  1431.          end;
  1432.  
  1433. (*******************************************)
  1434. (* CALL[]    : CALL function               *)
  1435. (* CodeRange : $2B                         *)
  1436.  
  1437.    $2B : begin
  1438.           if not Pop(L) then goto ErrorLabel;
  1439.  
  1440.           if ( word(L) >= FDefs.N ) or
  1441.              ( not FDefs.I^[L].Active ) then
  1442.             begin
  1443.               Error := TT_ErrMsg_Invalid_Reference;
  1444.               goto ErrorLabel;
  1445.             end;
  1446.  
  1447.           if CallTop >= CallSize then
  1448.             begin
  1449.               Error := TT_ErrMsg_Stack_Overflow;
  1450.               goto ErrorLabel;
  1451.             end;
  1452.  
  1453.           with CallStack^[CallTop] do
  1454.             begin
  1455.               Caller_Range := Cur_Range;
  1456.               Caller_IP    := IP+1;
  1457.               Cur_Count    := 1;
  1458.               Cur_Restart  := FDefs.I^[L].Start;
  1459.             end;
  1460.  
  1461.           inc( CallTop );
  1462.  
  1463.           with FDefs.I^[L] do
  1464.             if not Goto_CodeRange( Range, Start ) then
  1465.               goto ErrorLabel;
  1466.  
  1467.           goto SuiteLabel;
  1468.          end;
  1469.  
  1470. (*******************************************)
  1471. (* LOOPCALL[]: LOOP and CALL function      *)
  1472. (* CodeRange : $2A                         *)
  1473.  
  1474.    $2A : begin
  1475.           if not Pop2( K, L ) then goto ErrorLabel;
  1476.  
  1477.           if ( word(K) >= FDefs.N ) or
  1478.              ( not FDefs.I^[K].Active ) then
  1479.             begin
  1480.               Error := TT_ErrMsg_Invalid_Reference;
  1481.               goto ErrorLabel;
  1482.             end;
  1483.  
  1484.           if CallTop >= CallSize then
  1485.             begin
  1486.               Error := TT_ErrMsg_Stack_Overflow;
  1487.               goto ErrorLabel;
  1488.             end;
  1489.  
  1490.           if L > 0 then
  1491.             begin
  1492.               with CallStack^[CallTop] do
  1493.                 begin
  1494.                   Caller_Range := Cur_Range;
  1495.                   Caller_IP    := IP+1;
  1496.                   Cur_Count    := L;
  1497.                   Cur_Restart  := FDefs.I^[K].Start;
  1498.                 end;
  1499.  
  1500.               inc( CallTop );
  1501.  
  1502.               with FDefs.I^[K] do
  1503.                 if not Goto_CodeRange( Range, Start ) then
  1504.                   goto ErrorLabel;
  1505.  
  1506.               goto SuiteLabel;
  1507.             end;
  1508.  
  1509.         end;
  1510.  
  1511. (*******************************************)
  1512. (* IDEF[]    : Instruction DEFinition      *)
  1513. (* CodeRange : $89                         *)
  1514.  
  1515.    $89 : begin
  1516.            if not Pop(L) then goto ErrorLabel;
  1517.  
  1518.            A := 0;
  1519.  
  1520.            while ( A < IDefs.N ) do
  1521.              with IDefs.I^[A] do
  1522.                begin
  1523.                  if not Active then
  1524.                    begin
  1525.                      Opcode := L;
  1526.                      Start  := IP+1;
  1527.                      Range  := Cur_Range;
  1528.                      Active := True;
  1529.                      A      := IDefs.N;
  1530.  
  1531.                       (* now skip the whole function definition *)
  1532.                       (* we don't allow nested IDEFS & FDEFs    *)
  1533.  
  1534.                      while SkipCode do
  1535.                        case Code^[IP] of
  1536.  
  1537.                          $89,  (* IDEF *)
  1538.                          $2C : (* FDEF *)
  1539.                                begin
  1540.                                  Error := TT_ErrMsg_Nested_Defs;
  1541.                                  goto ErrorLabel;
  1542.                                end;
  1543.  
  1544.                          $2D : (* ENDF *)
  1545.                                begin
  1546.                                  SkipCode;
  1547.                                  goto SuiteLabel;
  1548.                                end;
  1549.                        end;
  1550.  
  1551.                      goto ErrorLabel;
  1552.  
  1553.                    end
  1554.                  else
  1555.                    inc( A );
  1556.                end;
  1557.          end;
  1558.  
  1559. (****************************************************************)
  1560. (*                                                              *)
  1561. (* PUSHING DATA ONTO THE INTERPRETER STACK                      *)
  1562. (*                                                              *)
  1563. (*  Instructions appear in the specs' order                     *)
  1564. (*                                                              *)
  1565. (****************************************************************)
  1566.  
  1567. (*******************************************)
  1568. (* NPUSHB[]  : PUSH N Bytes                *)
  1569. (* CodeRange : $40                         *)
  1570.  
  1571.    $40 : begin
  1572.           if IP+1>=CodeSize then
  1573.            begin
  1574.             Error:=TT_ErrMsg_Code_Overflow;
  1575.             goto ErrorLabel;
  1576.            end;
  1577.  
  1578.           L:=Code^[IP+1];
  1579.           if IP+1+L>=CodeSize then
  1580.            begin
  1581.             Error:=TT_ErrMsg_Code_Overflow;
  1582.             goto ErrorLabel;
  1583.            end;
  1584.  
  1585.           for K:=1 to L do
  1586.            if not Push( Code^[IP+1+K] ) then goto ErrorLabel;
  1587.  
  1588.          end;
  1589.  
  1590. (*******************************************)
  1591. (* NPUSHW[]  : PUSH N Words                *)
  1592. (* CodeRange : $41                         *)
  1593.  
  1594.    $41 : begin
  1595.           if IP+1>=CodeSize then
  1596.            begin
  1597.             Error:=TT_ErrMsg_Code_Overflow;
  1598.             goto ErrorLabel;
  1599.            end;
  1600.  
  1601.           L:=Code^[IP+1];
  1602.           if IP+1+2*L>=CodeSize then
  1603.            begin
  1604.             Error:=TT_ErrMsg_Code_Overflow;
  1605.             goto ErrorLabel;
  1606.            end;
  1607.  
  1608.           inc( IP, 2 );
  1609.           for K:=1 to L do
  1610.            begin
  1611.             A:=GetShort;
  1612.             if not Push( A ) then goto ErrorLabel;
  1613.            end;
  1614.  
  1615.           goto SuiteLabel;
  1616.          end;
  1617.  
  1618. (*******************************************)
  1619. (* PUSHB[abc]: PUSH Bytes                  *)
  1620. (* CodeRange : $B0-$B7                     *)
  1621.  
  1622.    $B0..$B7 : begin
  1623.                L:=Opcode-$B0+1;
  1624.                if IP+L>=CodeSize then
  1625.                 begin
  1626.                  Error:=TT_ErrMsg_Code_Overflow;
  1627.                  goto ErrorLabel;
  1628.                 end;
  1629.  
  1630.                for K:=1 to L do
  1631.                 if not Push( Code^[IP+K] ) then goto ErrorLabel;
  1632.  
  1633.               end;
  1634.  
  1635. (*******************************************)
  1636. (* PUSHW[abc]: PUSH Words                  *)
  1637. (* CodeRange : $B8-$BF                     *)
  1638.  
  1639.    $B8..$BF : begin
  1640.                L:=Opcode-$B8+1;
  1641.                if IP+2*L>=CodeSize then
  1642.                 begin
  1643.                  Error:=TT_ErrMsg_Code_Overflow;
  1644.                  goto ErrorLabel;
  1645.                 end;
  1646.  
  1647.                inc( IP );
  1648.                for K:=1 to L do
  1649.                 begin
  1650.                  A := GetShort;
  1651.                  if not Push( A ) then goto ErrorLabel;
  1652.                 end;
  1653.  
  1654.                goto SuiteLabel;
  1655.               end;
  1656.  
  1657. (****************************************************************)
  1658. (*                                                              *)
  1659. (* MANAGING THE STORAGE AREA                                    *)
  1660. (*                                                              *)
  1661. (*  Instructions appear in the specs' order                     *)
  1662. (*                                                              *)
  1663. (****************************************************************)
  1664.  
  1665. (*******************************************)
  1666. (* RS[]      : Read Store                  *)
  1667. (* CodeRange : $43                         *)
  1668.  
  1669.    $43 : begin
  1670.           if not Pop(L) then goto ErrorLabel;
  1671.           if L>=StoreSize then
  1672.             begin
  1673.              Error:=TT_ErrMsg_Storage_Overflow;
  1674.              goto ErrorLabel;
  1675.             end;
  1676.           if not Push( Storage^[L] ) then goto ErrorLabel;
  1677.          end;
  1678.  
  1679. (*******************************************)
  1680. (* WS[]      : Write Store                 *)
  1681. (* CodeRange : $42                         *)
  1682.  
  1683.    $42 : begin
  1684.           if not Pop2( K, L ) then goto ErrorLabel;
  1685.  
  1686.           if L>=StoreSize then
  1687.             begin
  1688.              Error:=TT_ErrMsg_Storage_Overflow;
  1689.              goto ErrorLabel;
  1690.             end;
  1691.           Storage^[L]:=K;
  1692.          end;
  1693.  
  1694. (*******************************************)
  1695. (* WCVTP[]   : Write CVT in Pixel units    *)
  1696. (* CodeRange : $44                         *)
  1697.  
  1698.    $44 : begin
  1699.           if not Pop2( K, L ) then goto ErrorLabel;
  1700.  
  1701.           if L>=CvtSize then
  1702.            begin
  1703.             Error:=TT_ErrMsg_CVT_Overflow;
  1704.             goto ErrorLabel;
  1705.            end;
  1706.  
  1707.           CVT^[L]:=K;
  1708.          end;
  1709.  
  1710. (*******************************************)
  1711. (* WCVTF[]   : Write CVT in FUnits         *)
  1712. (* CodeRange : $70                         *)
  1713.  
  1714.    $70 : begin
  1715.           if not Pop2( K, L ) then goto ErrorLabel;
  1716.  
  1717.           if L>=CvtSize then
  1718.            begin
  1719.             Error:=TT_ErrMsg_CVT_Overflow;
  1720.             goto ErrorLabel;
  1721.            end;
  1722.  
  1723.           CVT^[L]:=Scaled(K);
  1724.          end;
  1725.  
  1726. (*******************************************)
  1727. (* RCVT[]    : Read CVT                    *)
  1728. (* CodeRange : $45                         *)
  1729.  
  1730.    $45 : begin
  1731.           if not Pop( L ) then goto ErrorLabel;
  1732.  
  1733.           if L >= CvtSize then
  1734.            begin
  1735.             Error:=TT_ErrMsg_CVT_Overflow;
  1736.             goto ErrorLabel;
  1737.            end;
  1738.  
  1739.           if not Push( CVT^[L] ) then goto ErrorLabel;
  1740.          end;
  1741.  
  1742. (****************************************************************)
  1743. (*                                                              *)
  1744. (* MANAGING THE GRAPHICS STATE                                  *)
  1745. (*                                                              *)
  1746. (*  Instructions appear in the specs' order                     *)
  1747. (*                                                              *)
  1748. (****************************************************************)
  1749.  
  1750. (*******************************************)
  1751. (* SVTCA[a]  : Set F and P vectors to axis *)
  1752. (* CodeRange : $00-$01                     *)
  1753.  
  1754.    $00..$01 : begin
  1755.                Case OpCode and 1 of
  1756.                 0 : A:=$0000;
  1757.                 1 : A:=$4000;
  1758.                end;
  1759.                B:=A xor $4000;
  1760.  
  1761.                GS.projVector.x:=A;
  1762.                GS.projVector.y:=B;
  1763.                GS.freeVector.x:=A;
  1764.                GS.freeVector.y:=B;
  1765.               end;
  1766.  
  1767. (*******************************************)
  1768. (* SPVTCA[a] : Set PVector to Axis         *)
  1769. (* CodeRange : $02-$03                     *)
  1770.  
  1771.    $02..$03 : begin
  1772.                Case OpCode and 1 of
  1773.                 0 : A:=$0000;
  1774.                 1 : A:=$4000;
  1775.                end;
  1776.                B:=A xor $4000;
  1777.  
  1778.                GS.projVector.x:=A;
  1779.                GS.projVector.y:=B;
  1780.               end;
  1781.  
  1782. (*******************************************)
  1783. (* SFVTCA[a] : Set FVector to Axis         *)
  1784. (* CodeRange : $04-$05                     *)
  1785.  
  1786.    $04..$05 : begin
  1787.                Case OpCode and 1 of
  1788.                 0 : A:=$0000;
  1789.                 1 : A:=$4000;
  1790.                end;
  1791.                B:=A xor $4000;
  1792.  
  1793.                GS.freeVector.x:=A;
  1794.                GS.freeVector.y:=B;
  1795.               end;
  1796.  
  1797.  
  1798. (*******************************************)
  1799. (* SPVTL[a]  : Set PVector to Line         *)
  1800. (* CodeRange : $06-$07                     *)
  1801.  
  1802.    $06..$07 : begin
  1803.                if not PopPoint2( K, L, zp1.N, zp2.N ) then
  1804.                  goto ErrorLabel;
  1805.  
  1806.                A:= zp2.Cur^[L].x-zp1.Cur^[K].x;
  1807.                B:= zp2.Cur^[L].y-zp1.Cur^[K].y;
  1808.  
  1809.                if OpCode and 1 <> 0 then
  1810.                 begin
  1811.                  C:=B;  (* CounterClockwise rotation *)
  1812.                  B:=A;
  1813.                  A:=-C;
  1814.                 end;
  1815.  
  1816.                if not Normalize( A, B, GS.projVector )
  1817.                  then goto ErrorLabel;
  1818.               end;
  1819.  
  1820. (*******************************************)
  1821. (* SFVTL[a]  : Set FVector to Line         *)
  1822. (* CodeRange : $08-$09                     *)
  1823.  
  1824.    $08..$09 : begin
  1825.                if not PopPoint2( K, L, zp1.N, zp2.N ) then
  1826.                  goto ErrorLabel;
  1827.  
  1828.                A:= zp2.Cur^[L].x-zp1.Cur^[K].x;
  1829.                B:= zp2.Cur^[L].y-zp1.Cur^[K].y;
  1830.  
  1831.                if OpCode and 1 <> 0 then
  1832.                 begin
  1833.                  C:=B;  (* CounterClockwise rotation *)
  1834.                  B:=A;
  1835.                  A:=-C;
  1836.                 end;
  1837.  
  1838.                if not Normalize( A, B, GS.freeVector )
  1839.                  then goto ErrorLabel;
  1840.               end;
  1841.  
  1842. (*******************************************)
  1843. (* SFVTPV[]  : Set FVector to PVector      *)
  1844. (* CodeRange : $0E                         *)
  1845.  
  1846.    $0E : with GS do freeVector := projVector;
  1847.  
  1848.  
  1849. (*******************************************)
  1850. (* SDPVTL[a] : Set Dual PVector to Line    *)
  1851. (* CodeRange : $86-$87                     *)
  1852.  
  1853.    $86..$87 : begin
  1854.                if not PopPoint2( K, L, Pts.N, Pts.N ) then
  1855.                  goto ErrorLabel;
  1856.  
  1857.                A:= Pts.Org^[L].x-Pts.Org^[K].x;
  1858.                B:= Pts.Org^[L].y-Pts.Org^[K].y;
  1859.  
  1860.                if OpCode = $89 then
  1861.                 begin
  1862.                  C:=B;  (* CounterClockwise rotation *)
  1863.                  B:=A;
  1864.                  A:=-C;
  1865.                 end;
  1866.  
  1867.                if not Normalize( A, B, GS.dualVector )
  1868.                  then goto ErrorLabel;
  1869.               end;
  1870.  
  1871. (*******************************************)
  1872. (* SPVFS[]   : Set PVector From Stack      *)
  1873. (* CodeRange : $0A                         *)
  1874.  
  1875.    $0A : begin
  1876.           if not Pop2( K, L ) then goto ErrorLabel;
  1877.           S:=K; K:=S;  (* Type Conversion, extends sign *)
  1878.           S:=L; L:=S;  (* Type conversion, extends sign *)
  1879.           if not Normalize( L, K, GS.projVector )
  1880.             then goto ErrorLabel;
  1881.          end;
  1882.  
  1883. (*******************************************)
  1884. (* SFVFS[]   : Set FVector From Stack      *)
  1885. (* CodeRange : $0B                         *)
  1886.  
  1887.    $0B : begin
  1888.           if not Pop2( K, L ) then goto ErrorLabel;
  1889.           S:=K; K:=S;  (* Type Conversion, extends sign *)
  1890.           S:=L; L:=S;  (* Type conversion, extends sign *)
  1891.           if not Normalize( L, K, GS.freeVector )
  1892.             then goto ErrorLabel;
  1893.          end;
  1894.  
  1895. (*******************************************)
  1896. (* GPV[]     : Get Projection Vector       *)
  1897. (* CodeRange : $0C                         *)
  1898.  
  1899.    $0C : begin
  1900.           (* Type Conversion *)
  1901.           with GS.projVector do
  1902.            if not Push2( word(x), word(y) ) then
  1903.             goto ErrorLabel;
  1904.          end;
  1905.  
  1906. (*******************************************)
  1907. (* GFV[]     : Get Freedom Vector          *)
  1908. (* CodeRange : $0D                         *)
  1909.  
  1910.    $0D : begin
  1911.           (* Type Conversion *)
  1912.           with GS.freeVector do
  1913.            if not Push2( word(x), word(y) ) then
  1914.             goto ErrorLabel;
  1915.          end;
  1916.  
  1917.  
  1918. (*******************************************)
  1919. (* SRP0[]    : Set Reference Point 0       *)
  1920. (* CodeRange : $10                         *)
  1921.  
  1922.    $10 : begin
  1923.           if not Pop(L) then goto ErrorLabel;
  1924.           GS.RP0:=L;
  1925.          end;
  1926.  
  1927.  
  1928. (*******************************************)
  1929. (* SRP1[]    : Set Reference Point 1       *)
  1930. (* CodeRange : $11                         *)
  1931.  
  1932.    $11 : begin
  1933.           if not Pop(L) then goto ErrorLabel;
  1934.           GS.RP1:=L;
  1935.          end;
  1936.  
  1937.  
  1938. (*******************************************)
  1939. (* SRP2[]    : Set Reference Point 2       *)
  1940. (* CodeRange : $12                         *)
  1941.  
  1942.    $12 : begin
  1943.           if not Pop(L) then goto ErrorLabel;
  1944.           GS.RP2:=L;
  1945.          end;
  1946.  
  1947.  
  1948. (*******************************************)
  1949. (* SZP0[]    : Set Zone Pointer 0          *)
  1950. (* CodeRange : $13                         *)
  1951.  
  1952.    $13 : begin
  1953.           if not PopPoint( L, 2 ) then goto ErrorLabel;
  1954.           GS.Gep0:=L;
  1955.           if L=0 then zp0:=Twilight else zp0:=Pts;
  1956.          end;
  1957.  
  1958.  
  1959. (*******************************************)
  1960. (* SZP1[]    : Set Zone Pointer 1          *)
  1961. (* CodeRange : $14                         *)
  1962.  
  1963.    $14 : begin
  1964.           if not PopPoint( L, 2 ) then goto ErrorLabel;
  1965.           GS.Gep1:=L;
  1966.           if L=0 then zp1:=Twilight else zp1:=Pts;
  1967.          end;
  1968.  
  1969.  
  1970. (*******************************************)
  1971. (* SZP2[]    : Set Zone Pointer 2          *)
  1972. (* CodeRange : $15                         *)
  1973.  
  1974.    $15 : begin
  1975.           if not PopPoint( L, 2 ) then goto ErrorLabel;
  1976.           GS.Gep2:=L;
  1977.           if L=0 then zp2:=Twilight else zp2:=Pts;
  1978.          end;
  1979.  
  1980.  
  1981. (*******************************************)
  1982. (* SZPS[]    : Set Zone Pointers           *)
  1983. (* CodeRange : $16                         *)
  1984.  
  1985.    $16 : begin
  1986.           if not PopPoint( L, 2 ) then goto ErrorLabel;
  1987.           GS.Gep0:=L; if L=0 then zp0:=Twilight else zp0:=Pts;
  1988.           GS.Gep1:=L; zp1:=zp0;
  1989.           GS.Gep2:=L; zp2:=zp0;
  1990.          end;
  1991.  
  1992.  
  1993. (*******************************************)
  1994. (* RTHG[]    : Round To Half Grid          *)
  1995. (* CodeRange : $19                         *)
  1996.  
  1997.    $19 : GS.RoundState:=TTRoundToHalfGrid;
  1998.  
  1999.  
  2000. (*******************************************)
  2001. (* RTG[]     : Round To Grid               *)
  2002. (* CodeRange : $18                         *)
  2003.  
  2004.    $18 : GS.RoundState:=TTRoundToGrid;
  2005.  
  2006.  
  2007. (*******************************************)
  2008. (* RTDG[]    : Round To Double Grid        *)
  2009. (* CodeRange : $3D                         *)
  2010.  
  2011.    $3D : GS.RoundState:=TTRoundToDoubleGrid;
  2012.  
  2013.  
  2014. (*******************************************)
  2015. (* RUTG[]    : Round Up To Grid            *)
  2016. (* CodeRange : $7C                         *)
  2017.  
  2018.    $7C : GS.RoundState:=TTRoundUpToGrid;
  2019.  
  2020.  
  2021. (*******************************************)
  2022. (* RDTG[]    : Round Down To Grid          *)
  2023. (* CodeRange : $7D                         *)
  2024.  
  2025.    $7D : GS.RoundState:=TTRoundDownToGrid;
  2026.  
  2027.  
  2028. (*******************************************)
  2029. (* ROFF[]    : Round OFF                   *)
  2030. (* CodeRange : $7A                         *)
  2031.  
  2032.    $7A : GS.RoundState:=TTRoundOff;
  2033.  
  2034.  
  2035. (*******************************************)
  2036. (* SROUND[]  : Super ROUND                 *)
  2037. (* CodeRange : $76                         *)
  2038.  
  2039.    $76 : begin
  2040.           if not Pop(L) then goto ErrorLabel;
  2041.           SetSuperRound( $4000, L );
  2042.           GS.RoundState:=TTRoundSuper;
  2043.          end;
  2044.  
  2045.  
  2046. (*******************************************)
  2047. (* S45ROUND[]: Super ROUND 45 degrees      *)
  2048. (* CodeRange : $77                         *)
  2049.  
  2050.    $77 : begin
  2051.           if not Pop(L) then goto ErrorLabel;
  2052.           SetSuperRound( $2D41, L );
  2053.           GS.RoundState:=TTRoundSuper;
  2054.          end;
  2055.  
  2056.  
  2057. (*******************************************)
  2058. (* SLOOP[]   : Set LOOP variable           *)
  2059. (* CodeRange : $17                         *)
  2060.  
  2061.    $17 : begin
  2062.           if not Pop(L) then goto ErrorLabel;
  2063.           GS.Loop:=L;
  2064.          end;
  2065.  
  2066. (*******************************************)
  2067. (* SMD[]     : Set Minimium Distance       *)
  2068. (* CodeRange : $1A                         *)
  2069.  
  2070.    $1A : begin
  2071.           if not Pop(L) then goto ErrorLabel;
  2072.           GS.minimumDistance := L;
  2073.          end;
  2074.  
  2075. (*******************************************)
  2076. (* INSTCTRL[]: INSTruction ConTRoL         *)
  2077. (* CodeRange : $8E                         *)
  2078.  
  2079.    $8E : begin
  2080.            if not Pop2( K, L ) then goto ErrorLabel;
  2081.            if ( K < 1 ) or ( K > 2 ) then
  2082.              begin
  2083.                Error := TT_ErrMsg_Bad_Argument;
  2084.                goto ErrorLabel;
  2085.              end;
  2086.  
  2087.            if L <> 0 then L := K;
  2088.            GS.instructControl := (GS.instructControl and not K) or L;
  2089.          end;
  2090.  
  2091. (*******************************************)
  2092. (* SCANCTRL[]: SCAN ConTRol                *)
  2093. (* CodeRange : $85                         *)
  2094.  
  2095.    $85 : begin
  2096.            if not Pop( K ) then goto ErrorLabel;
  2097.            (*  XXXX TO DO *)
  2098.            GS.scanControl := True;
  2099.          end;
  2100.  
  2101.  
  2102. (*******************************************)
  2103. (* SCANTYPE[]: SCAN TYPE                   *)
  2104. (* CodeRange : $8D                         *)
  2105.  
  2106.    $8D : begin
  2107.            if not Pop(K) then goto ErrorLabel;
  2108.            (* XXXX TO DO *)
  2109.          end;
  2110.  
  2111.  
  2112. (**********************************************)
  2113. (* SCVTCI[]  : Set Control Value Table Cut In *)
  2114. (* CodeRange : $1D                            *)
  2115.  
  2116.    $1D : begin
  2117.           if not Pop(L) then goto ErrorLabel;
  2118.           GS.controlValueCutIn := L;
  2119.          end;
  2120.  
  2121.  
  2122. (**********************************************)
  2123. (* SSWCI[]   : Set Single Width Cut In        *)
  2124. (* CodeRange : $1E                            *)
  2125.  
  2126.    $1E : begin
  2127.           if not Pop(L) then goto ErrorLabel;
  2128.           GS.singleWidthCutIn := L;
  2129.          end;
  2130.  
  2131.  
  2132. (**********************************************)
  2133. (* SSW[]     : Set Single Width               *)
  2134. (* CodeRange : $1F                            *)
  2135.  
  2136.    $1F : begin
  2137.           if not Pop(L) then goto ErrorLabel;
  2138.           GS.singleWidthValue := L;
  2139.          end;
  2140.  
  2141.  
  2142. (**********************************************)
  2143. (* FLIPON[]  : Set Auto_flip to On            *)
  2144. (* CodeRange : $4D                            *)
  2145.  
  2146.    $4D : GS.autoFlip := TRUE;
  2147.  
  2148.  
  2149. (**********************************************)
  2150. (* FLIPOFF[] : Set Auto_flip to Off           *)
  2151. (* CodeRange : $4E                            *)
  2152.  
  2153.    $4E : GS.autoFlip := FALSE;
  2154.  
  2155.  
  2156. (**********************************************)
  2157. (* SANGW[]   : Set Angle Weigth               *)
  2158. (* CodeRange : $7E                            *)
  2159.  
  2160.    $7E : begin
  2161.          end; (* This instruction is not supported anymore *)
  2162.  
  2163.  
  2164. (**********************************************)
  2165. (* SDB[]     : Set Delta Base                 *)
  2166. (* CodeRange : $5E                            *)
  2167.  
  2168.    $5E : begin
  2169.           if not Pop(L) then goto ErrorLabel;
  2170.           GS.deltaBase := L;
  2171.          end;
  2172.  
  2173. (**********************************************)
  2174. (* SDS[]     : Set Delta Shift                *)
  2175. (* CodeRange : $5F                            *)
  2176.  
  2177.    $5F : begin
  2178.           if not Pop(L) then goto ErrorLabel;
  2179.           GS.deltaShift := L;
  2180.          end;
  2181.  
  2182.  
  2183. (**********************************************)
  2184. (* GC[a]     : Get Coordinate projected onto  *)
  2185. (* CodeRange : $46-$47                        *)
  2186.  
  2187.    $46..$47 : begin
  2188.                if not PopPoint( L, zp2.N ) then goto ErrorLabel;
  2189.  
  2190.                case Opcode and 1 of
  2191.                  0 : L:= Project( zp2.Org^[L], GS.projVector );
  2192.                  1 : L:= Project( zp2.Cur^[L], GS.projVector );
  2193.                 end;
  2194.  
  2195.                if not Push( L ) then
  2196.                 goto ErrorLabel;
  2197.               end;
  2198.  
  2199.  
  2200. (**********************************************)
  2201. (* SCFS[]    : Set Coordinate From Stack      *)
  2202. (* CodeRange : $48                            *)
  2203. (*                                            *)
  2204. (* Formule :                                  *)
  2205. (*                                            *)
  2206. (*   OA := OA + ( value - OA.p )/( f.p ) x f  *)
  2207. (*                                            *)
  2208.  
  2209.    $48 : begin
  2210.           if not Pop(K) or not PopPoint( L, zp2.N ) then
  2211.            goto ErrorLabel;
  2212.  
  2213.           if not MoveVec2( zp2.Cur^[L], K, zp2.Cur^[L] ) then
  2214.            goto ErrorLabel;
  2215.  
  2216.          end;
  2217.  
  2218. (**********************************************)
  2219. (* MD[a]     : Measure Distance               *)
  2220. (* CodeRange : $49-$4A                        *)
  2221.  
  2222.    $49..$4A : begin
  2223.                if not PopPoint2( K, L, zp0.n, zp1.n ) then
  2224.                  goto ErrorLabel;
  2225.  
  2226.                Case opcode and 1 of
  2227.  
  2228.                 1 : begin
  2229.                      Vec.x := zp1.Org^[L].x - zp0.Org^[L].x;
  2230.                      Vec.y := zp1.Org^[L].y - zp1.Org^[L].y;
  2231.                     end;
  2232.  
  2233.                 0 : begin
  2234.                      Vec.x := zp1.Cur^[L].x - zp0.Cur^[L].x;
  2235.                      Vec.y := zp1.Cur^[L].y - zp0.Cur^[L].y;
  2236.                     end;
  2237.                end;
  2238.  
  2239.                L := Project( Vec, GS.projVector );
  2240.                if not Push(L) then goto ErrorLabel;
  2241.               end;
  2242.  
  2243. (**********************************************)
  2244. (* MPPEM[]   : Measure Pixel Per EM           *)
  2245. (* CodeRange : $4B                            *)
  2246.  
  2247.    $4B : if not Push( Scale1 div 72 ) then
  2248.           goto ErrorLabel;
  2249.  
  2250.          (* NOTE : we return an integer, not a F26dot6 !!    *)
  2251.          (* XXXX   and we ASSUME a device with SQUARE pixels *)
  2252.  
  2253. (**********************************************)
  2254. (* MPS[]     : Measure PointSize              *)
  2255. (* CodeRange : $4C                            *)
  2256.  
  2257.    $4C : if not Push( PointSize ) then goto ErrorLabel;
  2258.  
  2259.  
  2260.  
  2261. (****************************************************************)
  2262. (*                                                              *)
  2263. (* MANAGING OUTLINES                                            *)
  2264. (*                                                              *)
  2265. (*  Instructions appear in the specs' order                     *)
  2266. (*                                                              *)
  2267. (****************************************************************)
  2268.  
  2269.  
  2270. (**********************************************)
  2271. (* FLIPPT[]  : FLIP PoinT                     *)
  2272. (* CodeRange : $80                            *)
  2273.  
  2274.    $80 : begin
  2275.           if not PopPoint( L, pts.N ) then goto ErrorLabel;
  2276.  
  2277.           Pts.Touch^[L] := Pts.Touch^[L] xor TTFlagOnCurve;
  2278.           (* Do we need to use Loop ?? *)
  2279.          end;
  2280.  
  2281. (**********************************************)
  2282. (* FLIPRGON[]: FLIP RanGe ON                  *)
  2283. (* CodeRange : $81                            *)
  2284.  
  2285.    $81 : begin
  2286.           if not PopPoint2( K, L, Pts.N, Pts.N ) then
  2287.             goto ErrorLabel;
  2288.  
  2289.           for A:=L to K do
  2290.            Pts.Touch^[L] := Pts.Touch^[L] or TTFlagOnCurve;
  2291.          end;
  2292.  
  2293. (**********************************************)
  2294. (* FLIPRGOFF : FLIP RanGe OFF                 *)
  2295. (* CodeRange : $82                            *)
  2296.  
  2297.    $82 : begin
  2298.           if not PopPoint2( K, L, Pts.N, Pts.N ) then
  2299.             goto ErrorLabel;
  2300.  
  2301.           for A:=L to K do
  2302.            Pts.Touch^[L] := Pts.Touch^[L] and not TTFlagOnCurve;
  2303.          end;
  2304.  
  2305. (**********************************************)
  2306. (* SHP[a]    : SHift Point by the last point  *)
  2307. (* CodeRange : $32-33                         *)
  2308.  
  2309.    $32..$33 : begin
  2310.                if not PopPoint( L, zp2.n ) then
  2311.                  goto ErrorLabel;
  2312.  
  2313.                case Opcode and 1 of
  2314.                 0 : begin A := GS.rp2; zp := zp1; end;
  2315.                 1 : begin A := GS.rp1; zp := zp0; end;
  2316.                end;
  2317.  
  2318.                if A>zp.N then
  2319.                 begin
  2320.                  Error:=TT_ErrMsg_Invalid_Reference;
  2321.                  goto ErrorLabel;
  2322.                 end;
  2323.  
  2324.                Vec.x := zp.Cur^[A].x - zp.Org^[A].x;
  2325.                Vec.y := zp.Cur^[A].y - zp.Org^[A].y;
  2326.  
  2327.                K := Project( Vec, GS.projVector );
  2328.                if not MoveVec1( zp2.Cur^[L], K ) then goto ErrorLabel;
  2329.  
  2330.                Touch( zp2.Touch^[L] );
  2331.               end;
  2332.  
  2333.  
  2334. (**********************************************)
  2335. (* SHC[a]    : SHift Contour                  *)
  2336. (* CodeRange : $34-35                         *)
  2337.  
  2338.    $34..$35 : begin
  2339.                if not PopPoint( L, Contours.N ) then
  2340.                 goto ErrorLabel;
  2341.  
  2342.                case Opcode and 1 of
  2343.                 0 : begin A := GS.rp2; zp := zp1; end;
  2344.                 1 : begin A := GS.rp1; zp := zp0; end;
  2345.                end;
  2346.  
  2347.                if A >= zp.N then
  2348.                 begin
  2349.                  Error:=TT_ErrMsg_Invalid_Reference;
  2350.                  goto ErrorLabel;
  2351.                 end;
  2352.  
  2353.                Vec.x := zp.Cur^[A].x - zp.Org^[A].x;
  2354.                Vec.y := zp.Cur^[A].y - zp.Org^[A].y;
  2355.  
  2356.                K := Project( Vec, GS.projVector );
  2357.  
  2358.                if zp.Cur <> zp2.Cur then
  2359.                 begin
  2360.                  with Contours.C^[L] do
  2361.                   for I:=First to Last do
  2362.                   begin
  2363.                    if not MoveVec1( zp2.Cur^[I], K ) then goto ErrorLabel;
  2364.                    Touch( zp2.Touch^[I] );
  2365.                   end
  2366.                 end
  2367.  
  2368.                else
  2369.                 (* We must not move the reference point if it is *)
  2370.                 (* the current glyph                             *)
  2371.                 with Contours.C^[L] do
  2372.                  for I:=First to Last do
  2373.                   if I<>A then if not MoveVec1( zp2.Cur^[I], K ) then
  2374.                        goto ErrorLabel
  2375.                      else
  2376.                        Touch( zp2.Touch^[I] );
  2377.               end;
  2378.  
  2379.  
  2380. (**********************************************)
  2381. (* SHZ[a]    : SHift Zone                     *)
  2382. (* CodeRange : $36-37                         *)
  2383.  
  2384.    $36..$37 : begin
  2385.                if not PopPoint( L, 2 ) then
  2386.                 goto ErrorLabel;
  2387.  
  2388.                if L<>0 then zp2:=Pts else zp2:=Twilight;
  2389.  
  2390.                case Opcode and 1 of
  2391.                 0 : begin A := GS.rp2; zp := zp1; end;
  2392.                 1 : begin A := GS.rp1; zp := zp0; end;
  2393.                end;
  2394.  
  2395.                if A>zp.N then
  2396.                 begin
  2397.                  Error:=TT_ErrMsg_Invalid_Reference;
  2398.                  goto ErrorLabel;
  2399.                 end;
  2400.  
  2401.                Vec.x := zp.Cur^[A].x - zp.Org^[A].x;
  2402.                Vec.y := zp.Cur^[A].y - zp.Org^[A].y;
  2403.  
  2404.                K := Project( Vec, GS.projVector );
  2405.  
  2406.                (* NOTE : The Reference Point will be   *)
  2407.                (*        shifted with all other points *)
  2408.  
  2409.                for I:=0 to zp.N-1 do
  2410.                 if not MoveVec1( zp2.Cur^[I], K ) then
  2411.                  goto ErrorLabel;
  2412.               end;
  2413.  
  2414.  
  2415. (**********************************************)
  2416. (* SHPIX[]   : SHift points by a PIXel amount *)
  2417. (* CodeRange : $38                            *)
  2418.  
  2419.    $38 : begin
  2420.           if not Pop(L) then goto ErrorLabel;
  2421.  
  2422.           A := MulDiv( GS.freeVector.x, L, $4000 );
  2423.           B := MulDiv( GS.freeVector.y, L, $4000 );
  2424.  
  2425.           while GS.loop > 0 do
  2426.  
  2427.            begin
  2428.             if not PopPoint( K, zp2.N ) then goto ErrorLabel;
  2429.  
  2430.             with zp2.Cur^[K] do
  2431.              begin
  2432.               inc( X, A );
  2433.               inc( Y, B );
  2434.              end;
  2435.  
  2436.             Touch( zp2.Touch^[K] );
  2437.  
  2438.             dec( GS.loop );
  2439.            end;
  2440.          end;
  2441.  
  2442.  
  2443. (**********************************************)
  2444. (* MSIRP[a]  : Move Stack Indirect Relative   *)
  2445. (* CodeRange : $3A-$3B                        *)
  2446.  
  2447.    $3A..$3B : begin
  2448.                if not Pop(L) or not PopPoint( K, zp1.N )
  2449.                 then goto ErrorLabel;
  2450.  
  2451.                with zp1.Cur^[K] do
  2452.                 begin
  2453.                  Vec.x := x - zp0.Cur^[GS.rp0].x;
  2454.                  Vec.y := y - zp0.Cur^[GS.rp0].y;
  2455.                 end;
  2456.  
  2457.                if not MoveVec2( zp1.Cur^[K], L, Vec ) then
  2458.                 goto ErrorLabel;
  2459.  
  2460.                Touch( zp1.Touch^[K] );
  2461.  
  2462.                if Opcode and 1 <> 0 then GS.rp0 := K;
  2463.               end;
  2464.  
  2465.  
  2466. (**********************************************)
  2467. (* MDAP[a]   : Move Direct Absolute Point     *)
  2468. (* CodeRange : $2E-$2F                        *)
  2469.  
  2470.    $2E..$2F : begin
  2471.                if not PopPoint( L, zp0.N ) then
  2472.                 goto ErrorLabel;
  2473.  
  2474.                GS.rp0 := L;
  2475.                GS.rp1 := L;
  2476.  
  2477.                if Opcode and 1 <> 0 then RoundPoint( zp0.Cur^[L] );
  2478.                Touch( zp0.Touch^[L] );
  2479.               end;
  2480.  
  2481. (**********************************************)
  2482. (* MIAP[a]   : Move Indirect Absolute Point   *)
  2483. (* CodeRange : $3E-$3F                        *)
  2484.  
  2485.    $3E..$3F : begin
  2486.                if not PopPoint( K, CVTSize ) or
  2487.                   not PopPoint( L, zp0.N ) then
  2488.                  goto ErrorLabel;
  2489.  
  2490.                K := CVT^[K];
  2491.  
  2492.                if OpCode and 1 <> 0 then
  2493.                 begin
  2494.                  A := Project( zp0.Cur^[L], GS.projVector );
  2495.                  (* XXX TODO : autoflip *)
  2496.                  if Abs( K-A ) > GS.controlValueCutIn then K:=A;
  2497.                  K:=ToRound(K);
  2498.                 end;
  2499.  
  2500.                with zp0.Cur^[L] do
  2501.                 begin
  2502.                  X := MulDiv( GS.projVector.x, K, $4000 );
  2503.                  Y := MulDiv( GS.projVector.y, K, $4000 );
  2504.                 end;
  2505.  
  2506.                zp0.Touch^[L] := zp0.Touch^[L] or TTFlagTouchedBoth;
  2507.  
  2508.                GS.rp0 := L;
  2509.                GS.rp1 := L;
  2510.               end;
  2511.  
  2512.  
  2513. (**********************************************)
  2514. (* MDRP[abcde] : Move Direct Relative Point   *)
  2515. (* CodeRange   : $C0-$DF                      *)
  2516.  
  2517.    $C0..$DF : begin
  2518.                if not PopPoint( L, zp1.N ) then
  2519.                  goto ErrorLabel;
  2520.  
  2521.                Vec.x := zp1.Org^[L].x - zp0.Org^[GS.rp0].x;
  2522.                Vec.y := zp1.Org^[L].y - zp0.Org^[GS.rp0].y;
  2523.  
  2524.                K := Project( Vec, GS.projVector );
  2525.  
  2526.                if K>=0 then Sign:=False
  2527.                 else
  2528.                  begin
  2529.                   Sign:=True;
  2530.                   K:=-K;
  2531.                  end;
  2532.  
  2533.                if K < GS.singleWidthCutIn then
  2534.                    K := GS.singleWidthValue;
  2535.  
  2536.                if Opcode and 8 <> 0 then
  2537.                 if K<GS.minimumDistance then K:=GS.minimumDistance;
  2538.  
  2539.                if Opcode and 4 <> 0 then
  2540.                  K := ToRound(K);
  2541.  
  2542.                if not Compensate( K, Opcode and 3 ) then
  2543.                  goto ErrorLabel;
  2544.  
  2545.                if Sign then K:=-K;
  2546.  
  2547.                Vec.x := zp1.Cur^[L].x - zp0.Cur^[GS.rp0].x;
  2548.                Vec.y := zp1.Cur^[L].y - zp0.Cur^[GS.rp0].y;
  2549.  
  2550.                if not MoveVec2( zp1.Cur^[L], K, Vec ) then
  2551.                  goto ErrorLabel;
  2552.  
  2553.                Touch( zp1.Touch^[L] );
  2554.  
  2555.                if Opcode and 16 <> 0 then GS.rp0 := L;
  2556.               end;
  2557.  
  2558.  
  2559. (**********************************************)
  2560. (* MIRP[abcde] : Move Indirect Relative Point *)
  2561. (* CodeRange   : $E0-$FF                      *)
  2562.  
  2563.    $E0..$FF : begin
  2564.                if not PopPoint2( K, L, CVTSize, zp1.N ) then
  2565.                  goto ErrorLabel;
  2566.  
  2567.                Vec.x := zp1.Cur^[L].x - zp0.Cur^[GS.rp0].x;
  2568.                Vec.y := zp1.Cur^[L].y - zp0.Cur^[GS.rp0].y;
  2569.  
  2570.                A := Project( Vec, GS.projVector );
  2571.  
  2572.                if A>=0 then Sign:=False
  2573.                 else
  2574.                  begin
  2575.                   Sign:=True;
  2576.                   A:=-A;
  2577.                  end;
  2578.  
  2579.                if Opcode and 4 <> 0 then
  2580.                 if A < GS.controlValueCutIn then
  2581.                   A := CVT^[K];
  2582.  
  2583.                if A < GS.singleWidthCutIn then
  2584.                    A := GS.singleWidthValue;
  2585.  
  2586.                if Opcode and 8 <> 0 then
  2587.                 if A<GS.minimumDistance then A:=GS.minimumDistance;
  2588.  
  2589.                if Opcode and 4 <> 0 then
  2590.                  A:=ToRound(A);
  2591.  
  2592.                if not Compensate( A, Opcode and 3 ) then
  2593.                  goto ErrorLabel;
  2594.  
  2595.                if Sign then A:=-A;
  2596.                (* XXX TODO autoflip *)
  2597.                if not MoveVec2( zp1.Cur^[L], K, Vec ) then
  2598.                  goto ErrorLabel;
  2599.  
  2600.                Touch( zp1.Touch^[L] );
  2601.  
  2602.                if Opcode and 16 <> 0 then GS.rp0 := L;
  2603.               end;
  2604.  
  2605.  
  2606. (**********************************************)
  2607. (* ALIGNRP[]   : ALIGN Relative Point         *)
  2608. (* CodeRange   : $3C                          *)
  2609.  
  2610.    $3C : begin
  2611.            if not PopPoint( L, zp1.N ) then
  2612.              goto ErrorLabel;
  2613.  
  2614.            Vec.x := zp1.Cur^[L].x - zp0.Cur^[GS.rp0].x;
  2615.            Vec.y := zp1.Cur^[L].y - zp0.Cur^[GS.rp0].y;
  2616.  
  2617.            if not MoveVec2( zp1.Cur^[L], 0, Vec ) then
  2618.              goto ErrorLabel;
  2619.  
  2620.            Touch( zp1.Touch^[L] );
  2621.           end;
  2622.  
  2623.  
  2624. (**********************************************)
  2625. (* AA[]        : Adjust Angle                 *)
  2626. (* CodeRange   : $7F                          *)
  2627.  
  2628.    $7F : ; (* Intentional - no longer supported *)
  2629.  
  2630.  
  2631. (**********************************************)
  2632. (* ISECT[]     : moves point to InterSECTion  *)
  2633. (* CodeRange   : $0F                          *)
  2634.  
  2635.    $0F : begin
  2636.            if not PopPoint2( L, K, zp0.N, zp0.N ) or
  2637.               not PopPoint2( B, A, zp1.N, zp1.N ) or
  2638.               not PopPoint( C, zp2.N ) then
  2639.             goto ErrorLabel;
  2640.  
  2641.            if not Intersect( zp1.Cur^[K], zp1.Cur^[L],
  2642.                              zp0.Cur^[A], zp0.Cur^[B],
  2643.                              Vec )
  2644.              then goto ErrorLabel;
  2645.  
  2646.            zp2.Cur^[C] := Vec;
  2647.            Touch( zp2.Touch^[C] );
  2648.          end;
  2649.  
  2650.  
  2651. (**********************************************)
  2652. (* ALIGNPTS[]  : ALIGN PoinTS                 *)
  2653. (* CodeRange   : $27                          *)
  2654.  
  2655.    $27 : begin
  2656.           if  not PopPoint2( K, L, zp0.N, zp1.N )       or
  2657.               not AlignVecs( zp0.Cur^[K], zp1.Cur^[L] )
  2658.             then
  2659.               goto ErrorLabel;
  2660.           zp0.Touch^[K] := zp0.Touch^[K] or TTFlagTouchedBoth;
  2661.           zp1.Touch^[L] := zp1.Touch^[L] or TTFlagTouchedBoth;
  2662.          end;
  2663.  
  2664.  
  2665.  
  2666. (**********************************************)
  2667. (* IP[]        : Interpolate Point            *)
  2668. (* CodeRange   : $39                          *)
  2669.  
  2670.    $39 : begin
  2671.           if not PopPoint( K, zp2.N ) then
  2672.             goto ErrorLabel;
  2673.  
  2674.           if not Barycentre( zp0.Org^[GS.rp1],
  2675.                              zp1.Org^[GS.rp2],
  2676.                              zp2.Org^[K],
  2677.                              zp0.Cur^[GS.rp1],
  2678.                              zp1.Cur^[GS.rp2],
  2679.                              zp2.Cur^[K]
  2680.                            )
  2681.             then
  2682.              goto ErrorLabel;
  2683.  
  2684.           Touch( zp2.Touch^[K] );
  2685.          end;
  2686.  
  2687.  
  2688. (**********************************************)
  2689. (* UTP[a]      : UnTouch Point                *)
  2690. (* CodeRange   : $29                          *)
  2691.  
  2692.    $29 : begin
  2693.           if not PopPoint( K, zp0.N ) then
  2694.            goto ErrorLabel;
  2695.           zp0.Touch^[K] := zp0.Touch^[K] and not TTFlagTouchedBoth;
  2696.           end;
  2697.  
  2698. (**********************************************)
  2699. (* IUP[a]      : Interpolate Untouched Points *)
  2700. (* CodeRange   : $30-$31                      *)
  2701.  
  2702.    $30 : begin
  2703.           if zp2.Cur = Twilight.Cur then
  2704.             begin
  2705.               Error := TT_ErrMsg_Interpolate_Twilight;
  2706.               goto ErrorLabel;
  2707.              end;
  2708.  
  2709.           with Pts, Contours do
  2710.            for A := 0 to N-1 do
  2711.             with C^[A] do
  2712.              for B := First to Last do
  2713.               begin
  2714.                if B = First then K:=Last else K:=B-1;
  2715.                if B = Last then L:=First else L:=L+1;
  2716.  
  2717.                if ( (not Touch^[B]) and (Touch^[K] and Touch^[L]) )
  2718.                    and TTFlagTouchedY <> 0
  2719.                  then
  2720.                    if not Interpolate( Org^[K].y,
  2721.                                        Org^[L].y,
  2722.                                        Org^[B].y,
  2723.                                        Cur^[K].y,
  2724.                                        Cur^[L].y,
  2725.                                        Cur^[B].y
  2726.                                      )
  2727.                     then
  2728.                       goto ErrorLabel;
  2729.  
  2730.               end;
  2731.          end;
  2732.  
  2733.    $31 : begin
  2734.           if zp2.Cur = Twilight.Cur then
  2735.             begin
  2736.               Error := TT_ErrMsg_Interpolate_Twilight;
  2737.               goto ErrorLabel;
  2738.              end;
  2739.  
  2740.           with Pts, Contours do
  2741.            for A := 0 to N-1 do
  2742.             with C^[A] do
  2743.              for B := First to Last do
  2744.               begin
  2745.                if B = First then K:=Last else K:=B-1;
  2746.                if B = Last then L:=First else L:=L+1;
  2747.  
  2748.                if ( (not Touch^[B]) and (Touch^[K] and Touch^[L]) )
  2749.                    and TTFlagTouchedX <> 0
  2750.                  then
  2751.                    if not Interpolate( Org^[K].x,
  2752.                                        Org^[L].x,
  2753.                                        Org^[B].x,
  2754.                                        Cur^[K].x,
  2755.                                        Cur^[L].x,
  2756.                                        Cur^[B].x
  2757.                                      )
  2758.                     then
  2759.                       goto ErrorLabel;
  2760.  
  2761.               end;
  2762.          end;
  2763.  
  2764. (**********************************************)
  2765. (* DELTAPn[]   : DELTA Exceptions P1, P2, P3  *)
  2766. (* CodeRange   : $5D,$71,$72                  *)
  2767.  
  2768.    $5D,
  2769.    $71,
  2770.    $72 : begin
  2771.           if not Pop(L) then goto ErrorLabel;
  2772.           for K:=1 to L do
  2773.             begin
  2774.               if not PopPoint( A, zp0.N ) or
  2775.                  not Pop(B)
  2776.                 then
  2777.                   goto ErrorLabel;
  2778.  
  2779.               C := ( B and $F0 ) shr 4;
  2780.  
  2781.               Case OpCode of
  2782.                 $5D : ;
  2783.                 $71 : C := C-16;
  2784.                 $72 : C := C-32;
  2785.                end;
  2786.  
  2787.               C := C + GS.deltaBase;
  2788.  
  2789.               if PointSize div 64 = C then
  2790.                 begin
  2791.                   B := (B and $F) - 8;
  2792.                   if B >= 0 then B:=B+1;
  2793.                   B := ( B*64 ) div ( 1 shl GS.deltaShift );
  2794.                   with zp0.Cur^[A] do
  2795.                     begin
  2796.                       inc( X, B*GS.freeVector.x div $4000 );
  2797.                       inc( Y, B*GS.freeVector.y div $4000 );
  2798.                     end;
  2799.                   Touch( zp0.Touch^[A] );
  2800.                 end;
  2801.             end;
  2802.          end;
  2803.  
  2804.  
  2805. (**********************************************)
  2806. (* DELTACn[]   : DELTA Exceptions C1, C2, C3  *)
  2807. (* CodeRange   : $73,$74,$75                  *)
  2808.  
  2809.    $73..$75 : begin
  2810.                if not Pop(L) then goto ErrorLabel;
  2811.                for K:=1 to L do
  2812.                  begin
  2813.                    if not PopPoint( A, CvtSize ) or
  2814.                       not Pop(B)
  2815.                      then
  2816.                        goto ErrorLabel;
  2817.  
  2818.                    C := ( B and $F0 ) shr 4;
  2819.  
  2820.                    Case OpCode of
  2821.                      $73 : ;
  2822.                      $74 : C := C-16;
  2823.                      $75 : C := C-32;
  2824.                     end;
  2825.  
  2826.                    C := C + GS.deltaBase;
  2827.  
  2828.                    if PointSize div 64 = C then
  2829.                      begin
  2830.                        B := (B and $F) - 8;
  2831.                        if B >= 0 then B:=B+1;
  2832.                        B := ( B*64 ) div ( 1 shl GS.deltaShift );
  2833.                        inc( CVT^[A], B );
  2834.                      end;
  2835.                  end;
  2836.               end;
  2837.  
  2838. (****************************************************************)
  2839. (*                                                              *)
  2840. (* MISC. INSTRUCTIONS                                           *)
  2841. (*                                                              *)
  2842. (****************************************************************)
  2843.  
  2844. (***********************************************************)
  2845. (* DEBUG[]     : DEBUG. Unsupported                        *)
  2846. (* CodeRange   : $4F                                       *)
  2847.  
  2848. (* NOTE : The original instruction pops a value from the stack *)
  2849.  
  2850.    $4F : begin
  2851.           Error := TT_ErrMsg_Debug_Opcode;
  2852.           goto ErrorLabel;
  2853.          end;
  2854.  
  2855.  
  2856. (**********************************************)
  2857. (* GETINFO[]   : GET INFOrmation              *)
  2858. (* CodeRange   : $88                          *)
  2859.  
  2860.    $88 : begin
  2861.           if not Pop(L) then goto ErrorLabel;
  2862.           K:=0;
  2863.  
  2864.           if L and 1 <> 0 then K := 3;
  2865.           (* We return then Windows 3.1 version number *)
  2866.           (* for the font scaler                       *)
  2867.  
  2868.           if false then K:=K or $80;
  2869.           (* Has the glyph been rotated ? *)
  2870.           (* XXXX TO DO *)
  2871.  
  2872.           if false then K:=K or $100;
  2873.           (* Has the glyph been stretched ? *)
  2874.           (* XXXX TO DO *)
  2875.  
  2876.           if not Push(K) then goto ErrorLabel;
  2877.          end;
  2878.  
  2879.    else
  2880.  
  2881. (*******************************************)
  2882. (* Instructions définies par le programme  *)
  2883. (* au moyen de IDEF/ENDI                   *)
  2884.  
  2885.     A := 0;
  2886.     while ( A < IDefs.N ) do
  2887.       with IDefs.I^[A] do
  2888.  
  2889.         if Active and ( Opcode = Opc ) then
  2890.           begin
  2891.             if CallTop >= CallSize then
  2892.               begin
  2893.                 Error := TT_ErrMsg_Invalid_Reference;
  2894.                 goto ErrorLabel;
  2895.               end;
  2896.  
  2897.             with CallStack^[CallTop] do
  2898.               begin
  2899.                 Caller_Range := Cur_Range;
  2900.                 Caller_IP    := IP+1;
  2901.                 Cur_Count    := 1;
  2902.                 Cur_Restart  := Start;
  2903.               end;
  2904.  
  2905.             if not Goto_CodeRange( Range, Start ) then
  2906.               goto ErrorLabel;
  2907.  
  2908.             goto SuiteLabel;
  2909.           end
  2910.         else
  2911.           inc(A);
  2912.  
  2913.       Error := TT_ErrMsg_Invalid_Opcode;
  2914.       goto ErrorLabel;
  2915.    end;
  2916.  
  2917.    SkipCode;
  2918.  
  2919. SuiteLabel:
  2920.  
  2921.    if (IP >= CodeSize) then
  2922.  
  2923.     if CallTop > 0 then
  2924.       begin
  2925.         Error := TT_ErrMsg_Code_Overflow;
  2926.         goto ErrorLabel;
  2927.       end
  2928.     else
  2929.       goto No_Error;
  2930.  
  2931.   until Instruction_Trap;
  2932.  
  2933. No_Error:
  2934.  
  2935.   Run := True;
  2936.   exit;
  2937.  
  2938. ErrorLabel:
  2939.  
  2940. (********************************************)
  2941. (* An error occured during execution. Quit  *)
  2942. (* quietly then..                           *)
  2943.  
  2944.   Run := False;
  2945.  
  2946. end;
  2947.  
  2948.  
  2949. (********************)
  2950. (* Init_Interpreter *)
  2951. (***********************************************************************)
  2952. (*                                                                     *)
  2953. (* This routine must be called before any execution, after the max     *)
  2954. (* profile table has been loaded.                                      *)
  2955. (*                                                                     *)
  2956. (* Please make sure the Font Storage Pool and the CVT have been        *)
  2957. (* allocated prior to any execution..                                  *)
  2958.  
  2959. function  Init_Interpreter( var Max : TMaxProfile ) : boolean;
  2960. var
  2961.   i, n : int;
  2962. begin
  2963.  
  2964.   Init_Interpreter := False;
  2965.   Error            := TT_ErrMsg_Storage_Overflow;
  2966.  
  2967.   (* First, allocate the stack segment *)
  2968.   if not Alloc( Max.maxStackElements * sizeof(LongInt), Pointer(Stack) )
  2969.     then exit;
  2970.   StackSize := Max.maxStackElements;
  2971.  
  2972.   (* Second, allocate Function & Instruction Defs tables *)
  2973.   IDefs.N := Max.maxInstructionDefs;
  2974.   if not Alloc( IDefs.N * sizeof( TDefRecord ), Pointer(IDefs.I) )
  2975.     then exit;
  2976.  
  2977.   for i := 0 to IDefs.N-1 do
  2978.     IDefs.I^[i].Active := False;
  2979.  
  2980.   FDefs.N := Max.maxFunctionDefs;
  2981.   if not Alloc( FDefs.N * sizeof( TDefRecord ), Pointer(FDefs.I) )
  2982.     then exit;
  2983.  
  2984.   for i := 0 to FDefs.N-1 do
  2985.     FDefs.I^[i].Active := False;
  2986.  
  2987.   (* Third, init the call stack, we currently support 8 nested calls *)
  2988.  
  2989.   CallTop  := 0;
  2990.   CallSize := 0;
  2991.   if not Alloc( sizeof(TCallRecord)*8, Pointer(CallStack) )
  2992.     then exit;
  2993.   CallSize := 8;
  2994.  
  2995.   (* Fourth, init the storage area, to zero *)
  2996.  
  2997.   Storage   := nil;
  2998.   StoreSize := 0;
  2999.   if not Alloc( Max.maxStorage*4, Pointer(Storage) )
  3000.     then exit;
  3001.   StoreSize := Max.maxStorage;
  3002.  
  3003.   (* Fifth, allocate the Two zones *)
  3004.  
  3005.   n := sizeof(TVector) * Max.maxTwilightPoints;
  3006.  
  3007.   if not Alloc( n, Pointer( Twilight.Org ) ) or
  3008.      not Alloc( n, Pointer( Twilight.Cur ) ) or
  3009.      not Alloc( Max.maxTwilightPoints, Pointer( Twilight.Touch ) ) then exit;
  3010.  
  3011.   for i := 0 to Max.maxTwilightPoints-1 do with Twilight.Org^[i] do
  3012.     begin
  3013.       x := 0;
  3014.       y := 0;
  3015.     end;
  3016.  
  3017.   for i := 0 to Max.maxTwilightPoints-1 do Twilight.Touch^[i]:=0;
  3018.  
  3019.   move( Twilight.Org^, Twilight.Cur^, n );
  3020.  
  3021.   Twilight.N := Max.maxTwilightPoints;
  3022.  
  3023.   (* Init the instruction pointer, this should be changed later by *)
  3024.   (* others parts of the program                                   *)
  3025.  
  3026.   Cur_Range  := 0;
  3027.   CodeRanges := 0;
  3028.   Code       := nil;
  3029.   IP         := 0;
  3030.   CodeSize   := 0;
  3031.  
  3032.   Instruction_Trap := False;
  3033.  
  3034.   Pts.N   := 0;
  3035.   Pts.Org := nil;
  3036.   Pts.Cur := nil;
  3037.  
  3038.   zp0 := Pts;
  3039.   zp1 := Pts;
  3040.   zp2 := Pts;
  3041.  
  3042.   Init_Interpreter := True;
  3043. end;
  3044.  
  3045. end.
  3046.